make CustomMouseCursor generic over BasicImage types
this contains an unfortunate hacky change to the BasicBlitMethod enum which used to be generic over a PixelType (same as BasicImage is currently). i really do not like this, but i could not find any solution to the problem. admittedly it's not the worst hack solution in the world, but it does technically allow calling code to pass colour values that are outside the supported range which may lead to odd results at runtime.
This commit is contained in:
parent
3e8ec9f73e
commit
f0095cf1dc
|
@ -5,22 +5,31 @@
|
||||||
//!
|
//!
|
||||||
//! Only a subset of the most common Bitmap drawing operations will be provided here.
|
//! Only a subset of the most common Bitmap drawing operations will be provided here.
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
use num_traits::{PrimInt, Unsigned};
|
use num_traits::{PrimInt, Unsigned};
|
||||||
|
|
||||||
use crate::graphics::indexed;
|
use crate::graphics::indexed;
|
||||||
use crate::math::Rect;
|
use crate::math::Rect;
|
||||||
|
|
||||||
pub enum BasicBlitMethod<PixelType>
|
// HACK: enum variant color arguments are sized to the max possible pixel type used across all supported bitmap variants
|
||||||
where PixelType: PrimInt + Unsigned {
|
// right now. for some reason, making this enum generic (e.g. `BasicBlitMethod<PixelType: PrimInt + Unsigned>`)
|
||||||
|
// resulted in some E0308 compile errors when trying to create enum variant values that contained args of the
|
||||||
|
// generic type. i could not find a solution to this. so i'll just do this hack approach for now. ugh.
|
||||||
|
pub enum BasicBlitMethod {
|
||||||
Solid,
|
Solid,
|
||||||
Transparent(PixelType),
|
Transparent(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait that provides "bit-depth-agnostic" access to bitmap drawing operations. This is useful for implementing
|
/// Trait that provides "bit-depth-agnostic" access to bitmap drawing operations. This is useful for implementing
|
||||||
/// drawing functionality that is to be made generic across all supported bitmap types and is not specific to
|
/// drawing functionality that is to be made generic across all supported bitmap types and is not specific to
|
||||||
/// any one pixel-depth. Note that this does not provide cross-bit-depth drawing support.
|
/// any one pixel-depth. Note that this does not provide cross-bit-depth drawing support.
|
||||||
pub trait BasicImage {
|
pub trait BasicImage: Sized {
|
||||||
type PixelType: PrimInt + Unsigned;
|
type PixelType: PrimInt + Unsigned;
|
||||||
|
type ErrorType: Error;
|
||||||
|
|
||||||
|
/// Creates a new bitmap with the specified dimensions, in pixels.
|
||||||
|
fn new(width: u32, height: u32) -> Result<Self, Self::ErrorType>;
|
||||||
|
|
||||||
/// Returns the width of the bitmap in pixels.
|
/// Returns the width of the bitmap in pixels.
|
||||||
fn width(&self) -> u32;
|
fn width(&self) -> u32;
|
||||||
|
@ -73,14 +82,14 @@ pub trait BasicImage {
|
||||||
|
|
||||||
fn blit_region(
|
fn blit_region(
|
||||||
&mut self,
|
&mut self,
|
||||||
method: BasicBlitMethod<Self::PixelType>,
|
method: BasicBlitMethod,
|
||||||
src: &Self,
|
src: &Self,
|
||||||
src_region: &Rect,
|
src_region: &Rect,
|
||||||
dest_x: i32,
|
dest_x: i32,
|
||||||
dest_y: i32
|
dest_y: i32
|
||||||
);
|
);
|
||||||
|
|
||||||
fn blit(&mut self, method: BasicBlitMethod<Self::PixelType>, src: &Self, x: i32, y: i32) {
|
fn blit(&mut self, method: BasicBlitMethod, src: &Self, x: i32, y: i32) {
|
||||||
let src_region = Rect::new(0, 0, src.width(), src.height());
|
let src_region = Rect::new(0, 0, src.width(), src.height());
|
||||||
self.blit_region(method, src, &src_region, x, y);
|
self.blit_region(method, src, &src_region, x, y);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +97,11 @@ pub trait BasicImage {
|
||||||
|
|
||||||
impl BasicImage for indexed::Bitmap {
|
impl BasicImage for indexed::Bitmap {
|
||||||
type PixelType = u8;
|
type PixelType = u8;
|
||||||
|
type ErrorType = indexed::BitmapError;
|
||||||
|
|
||||||
|
fn new(width: u32, height: u32) -> Result<Self, Self::ErrorType> {
|
||||||
|
Self::new(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn width(&self) -> u32 {
|
fn width(&self) -> u32 {
|
||||||
|
@ -156,15 +170,16 @@ impl BasicImage for indexed::Bitmap {
|
||||||
|
|
||||||
fn blit_region(
|
fn blit_region(
|
||||||
&mut self,
|
&mut self,
|
||||||
method: BasicBlitMethod<u8>,
|
method: BasicBlitMethod,
|
||||||
src: &Self,
|
src: &Self,
|
||||||
src_region: &Rect,
|
src_region: &Rect,
|
||||||
dest_x: i32,
|
dest_x: i32,
|
||||||
dest_y: i32
|
dest_y: i32
|
||||||
) {
|
) {
|
||||||
|
// HACK: pixel/color value downcasting. see "HACK" comment above BasicBlitMethod type def
|
||||||
let blit_method = match method {
|
let blit_method = match method {
|
||||||
BasicBlitMethod::Solid => indexed::BlitMethod::Solid,
|
BasicBlitMethod::Solid => indexed::BlitMethod::Solid,
|
||||||
BasicBlitMethod::Transparent(color) => indexed::BlitMethod::Transparent(color),
|
BasicBlitMethod::Transparent(color) => indexed::BlitMethod::Transparent(color as u8),
|
||||||
};
|
};
|
||||||
self.blit_region(blit_method, src, src_region, dest_x, dest_y)
|
self.blit_region(blit_method, src, src_region, dest_x, dest_y)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// that are not specific to just our 256 colour Bitmap functionality. whether this takes the form
|
// that are not specific to just our 256 colour Bitmap functionality. whether this takes the form
|
||||||
// of a generified CustomMouseCursor struct, or multiple versions ... well, i'm not quite sure yet!
|
// of a generified CustomMouseCursor struct, or multiple versions ... well, i'm not quite sure yet!
|
||||||
|
|
||||||
|
use crate::graphics::*;
|
||||||
use crate::graphics::indexed::*;
|
use crate::graphics::indexed::*;
|
||||||
use crate::math::*;
|
use crate::math::*;
|
||||||
|
|
||||||
|
@ -12,40 +13,34 @@ const DEFAULT_MOUSE_CURSOR_HOTSPOT_Y: u32 = 0;
|
||||||
const DEFAULT_MOUSE_CURSOR_WIDTH: usize = 16;
|
const DEFAULT_MOUSE_CURSOR_WIDTH: usize = 16;
|
||||||
const DEFAULT_MOUSE_CURSOR_HEIGHT: usize = 16;
|
const DEFAULT_MOUSE_CURSOR_HEIGHT: usize = 16;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
pub trait DefaultMouseCursorBitmaps<BitmapType>
|
||||||
const DEFAULT_MOUSE_CURSOR: [u8; DEFAULT_MOUSE_CURSOR_WIDTH * DEFAULT_MOUSE_CURSOR_HEIGHT] = [
|
where
|
||||||
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
BitmapType: BasicImage
|
||||||
0x00, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
{
|
||||||
0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
fn get_default() -> BitmapType;
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
}
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Provides custom mouse cursor rendering functionality via application provided [`Bitmap`]s (or falling back
|
/// Provides custom mouse cursor rendering functionality via application provided [`Bitmap`]s (or falling back
|
||||||
/// to a default cursor if none is set by the application). Custom cursor rendering is disabled by default.
|
/// to a default cursor if none is set by the application). Custom cursor rendering is disabled by default.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CustomMouseCursor {
|
pub struct CustomMouseCursor<BitmapType>
|
||||||
|
where
|
||||||
|
BitmapType: BasicImage
|
||||||
|
{
|
||||||
last_x: i32,
|
last_x: i32,
|
||||||
last_y: i32,
|
last_y: i32,
|
||||||
cursor: Bitmap,
|
cursor: BitmapType,
|
||||||
cursor_background: Bitmap,
|
cursor_background: BitmapType,
|
||||||
cursor_hotspot_x: u32,
|
cursor_hotspot_x: u32,
|
||||||
cursor_hotspot_y: u32,
|
cursor_hotspot_y: u32,
|
||||||
cursor_enabled: bool,
|
cursor_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomMouseCursor {
|
impl<BitmapType> CustomMouseCursor<BitmapType>
|
||||||
|
where
|
||||||
|
Self: DefaultMouseCursorBitmaps<BitmapType>,
|
||||||
|
BitmapType: BasicImage
|
||||||
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (cursor, cursor_background, cursor_hotspot_x, cursor_hotspot_y) = Self::get_default_mouse_cursor();
|
let (cursor, cursor_background, cursor_hotspot_x, cursor_hotspot_y) = Self::get_default_mouse_cursor();
|
||||||
|
|
||||||
|
@ -62,7 +57,7 @@ impl CustomMouseCursor {
|
||||||
|
|
||||||
/// Returns a reference to the current mouse cursor bitmap.
|
/// Returns a reference to the current mouse cursor bitmap.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cursor_bitmap(&self) -> &Bitmap {
|
pub fn cursor_bitmap(&self) -> &BitmapType {
|
||||||
&self.cursor
|
&self.cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,9 +93,9 @@ impl CustomMouseCursor {
|
||||||
/// * `cursor`: the bitmap to be used to display the mouse cursor on screen
|
/// * `cursor`: the bitmap to be used to display the mouse cursor on screen
|
||||||
/// * `hotspot_x`: the "hotspot" x coordinate
|
/// * `hotspot_x`: the "hotspot" x coordinate
|
||||||
/// * `hotspot_y`: the "hotspot" y coordinate.
|
/// * `hotspot_y`: the "hotspot" y coordinate.
|
||||||
pub fn set_mouse_cursor(&mut self, cursor: Bitmap, hotspot_x: u32, hotspot_y: u32) {
|
pub fn set_mouse_cursor(&mut self, cursor: BitmapType, hotspot_x: u32, hotspot_y: u32) {
|
||||||
self.cursor = cursor;
|
self.cursor = cursor;
|
||||||
self.cursor_background = Bitmap::new(self.cursor.width(), self.cursor.height()).unwrap();
|
self.cursor_background = BitmapType::new(self.cursor.width(), self.cursor.height()).unwrap();
|
||||||
self.cursor_hotspot_x = hotspot_x;
|
self.cursor_hotspot_x = hotspot_x;
|
||||||
self.cursor_hotspot_y = hotspot_y;
|
self.cursor_hotspot_y = hotspot_y;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +129,7 @@ impl CustomMouseCursor {
|
||||||
///
|
///
|
||||||
/// [`SystemResources`]: crate::system::SystemResources
|
/// [`SystemResources`]: crate::system::SystemResources
|
||||||
/// [`SystemResources::display`]: crate::system::SystemResources::display
|
/// [`SystemResources::display`]: crate::system::SystemResources::display
|
||||||
pub fn render(&mut self, dest: &mut Bitmap) {
|
pub fn render(&mut self, dest: &mut BitmapType) {
|
||||||
if !self.cursor_enabled {
|
if !self.cursor_enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -143,14 +138,15 @@ impl CustomMouseCursor {
|
||||||
|
|
||||||
// preserve existing background first
|
// preserve existing background first
|
||||||
self.cursor_background.blit_region(
|
self.cursor_background.blit_region(
|
||||||
BlitMethod::Solid,
|
BasicBlitMethod::Solid,
|
||||||
&dest,
|
&dest,
|
||||||
&Rect::new(x, y, self.cursor.width(), self.cursor.height()),
|
&Rect::new(x, y, self.cursor.width(), self.cursor.height()),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
dest.blit(BlitMethod::Transparent(255), &self.cursor, x, y);
|
let color = 255;
|
||||||
|
dest.blit(BasicBlitMethod::Transparent(color), &self.cursor, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restores the original destination bitmap contents where the mouse cursor bitmap was
|
/// Restores the original destination bitmap contents where the mouse cursor bitmap was
|
||||||
|
@ -164,13 +160,13 @@ impl CustomMouseCursor {
|
||||||
///
|
///
|
||||||
/// [`SystemResources`]: crate::system::SystemResources
|
/// [`SystemResources`]: crate::system::SystemResources
|
||||||
/// [`SystemResources::display`]: crate::system::SystemResources::display
|
/// [`SystemResources::display`]: crate::system::SystemResources::display
|
||||||
pub fn hide(&mut self, dest: &mut Bitmap) {
|
pub fn hide(&mut self, dest: &mut BitmapType) {
|
||||||
if !self.cursor_enabled {
|
if !self.cursor_enabled {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (x, y) = self.get_cursor_render_position();
|
let (x, y) = self.get_cursor_render_position();
|
||||||
dest.blit(BlitMethod::Solid, &self.cursor_background, x, y);
|
dest.blit(BasicBlitMethod::Solid, &self.cursor_background, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates current state from the given [`Mouse`] device's state, ensuring that subsequent calls to render
|
/// Updates current state from the given [`Mouse`] device's state, ensuring that subsequent calls to render
|
||||||
|
@ -183,15 +179,9 @@ impl CustomMouseCursor {
|
||||||
self.last_y = mouse.y;
|
self.last_y = mouse.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_default_mouse_cursor() -> (Bitmap, Bitmap, u32, u32) {
|
fn get_default_mouse_cursor() -> (BitmapType, BitmapType, u32, u32) {
|
||||||
let mut cursor = Bitmap::new(
|
let cursor = Self::get_default();
|
||||||
DEFAULT_MOUSE_CURSOR_WIDTH as u32,
|
let cursor_background = BitmapType::new(cursor.width(), cursor.height()).unwrap();
|
||||||
DEFAULT_MOUSE_CURSOR_HEIGHT as u32,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
cursor.pixels_mut().copy_from_slice(&DEFAULT_MOUSE_CURSOR);
|
|
||||||
|
|
||||||
let cursor_background = Bitmap::new(cursor.width(), cursor.height()).unwrap();
|
|
||||||
|
|
||||||
(
|
(
|
||||||
cursor,
|
cursor,
|
||||||
|
@ -201,3 +191,36 @@ impl CustomMouseCursor {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DefaultMouseCursorBitmaps<indexed::Bitmap> for CustomMouseCursor<indexed::Bitmap> {
|
||||||
|
fn get_default() -> Bitmap {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const CURSOR_PIXELS: [u8; DEFAULT_MOUSE_CURSOR_WIDTH * DEFAULT_MOUSE_CURSOR_HEIGHT] = [
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x0f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut cursor = Bitmap::new(
|
||||||
|
DEFAULT_MOUSE_CURSOR_WIDTH as u32,
|
||||||
|
DEFAULT_MOUSE_CURSOR_HEIGHT as u32,
|
||||||
|
).unwrap();
|
||||||
|
cursor.pixels_mut().copy_from_slice(&CURSOR_PIXELS);
|
||||||
|
cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: other DefaultMouseCursorBitmaps impl's here ... when the other bitmap types are added
|
||||||
|
|
|
@ -224,7 +224,7 @@ pub struct DosLike {
|
||||||
|
|
||||||
/// Manages custom mouse cursor graphics and state. Use this to set/unset a custom mouse cursor bitmap.
|
/// Manages custom mouse cursor graphics and state. Use this to set/unset a custom mouse cursor bitmap.
|
||||||
/// When set, rendering should occur automatically during calls to [`SystemResources::display`].
|
/// When set, rendering should occur automatically during calls to [`SystemResources::display`].
|
||||||
pub cursor: CustomMouseCursor,
|
pub cursor: CustomMouseCursor<Bitmap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for DosLike {
|
impl std::fmt::Debug for DosLike {
|
||||||
|
|
Loading…
Reference in a new issue