mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
710 lines
25 KiB
Rust
710 lines
25 KiB
Rust
#[macro_use]
|
|
extern crate pretty_assertions;
|
|
|
|
#[macro_use]
|
|
extern crate indoc;
|
|
|
|
mod helpers;
|
|
|
|
#[cfg(test)]
|
|
mod test_gen_rs {
|
|
use crate::helpers::generate_bindings;
|
|
|
|
#[test]
|
|
fn record_aliased() {
|
|
let module = indoc!(
|
|
r#"
|
|
MyRcd : { a : U64, b : I128 }
|
|
|
|
main : MyRcd
|
|
main = { a: 1u64, b: 2i128 }
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Default, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct MyRcd {
|
|
pub b: roc_std::I128,
|
|
pub a: u64,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn nested_record_aliased() {
|
|
let module = indoc!(
|
|
r#"
|
|
Outer : { x : Inner, y : Str, z : List U8 }
|
|
|
|
Inner : { a : U16, b : F32 }
|
|
|
|
main : Outer
|
|
main = { x: { a: 5, b: 24 }, y: "foo", z: [ 1, 2 ] }
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct Outer {
|
|
pub y: roc_std::RocStr,
|
|
pub z: roc_std::RocList<u8>,
|
|
pub x: Inner,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct Inner {
|
|
pub b: f32,
|
|
pub a: u16,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn record_anonymous() {
|
|
let module = "main = { a: 1u64, b: 2u128 }";
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Default, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct R1 {
|
|
pub b: roc_std::U128,
|
|
pub a: u64,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn nested_record_anonymous() {
|
|
let module = r#"main = { x: { a: 5u16, b: 24f32 }, y: "foo", z: [ 1u8, 2 ] }"#;
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct R1 {
|
|
pub y: roc_std::RocStr,
|
|
pub z: roc_std::RocList<u8>,
|
|
pub x: R2,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct R2 {
|
|
pub b: f32,
|
|
pub a: u16,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn tag_union_aliased() {
|
|
let module = indoc!(
|
|
r#"
|
|
NonRecursive : [ Foo Str, Bar U128, Blah I32, Baz ]
|
|
|
|
main : NonRecursive
|
|
main = Foo "blah"
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(u8)]
|
|
pub enum tag_NonRecursive {
|
|
Bar = 0,
|
|
Baz = 1,
|
|
Blah = 2,
|
|
Foo = 3,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub union union_NonRecursive {
|
|
Bar: roc_std::U128,
|
|
Blah: i32,
|
|
Foo: core::mem::ManuallyDrop<roc_std::RocStr>,
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct NonRecursive {
|
|
variant: union_NonRecursive,
|
|
tag: tag_NonRecursive,
|
|
}
|
|
|
|
impl NonRecursive {
|
|
pub fn tag(&self) -> tag_NonRecursive {
|
|
self.tag
|
|
}
|
|
|
|
/// Construct a tag named Bar, with the appropriate payload
|
|
pub fn Bar(payload: roc_std::U128) -> Self {
|
|
Self {
|
|
tag: tag_NonRecursive::Bar,
|
|
variant: union_NonRecursive {
|
|
Bar: payload
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Bar and convert it to Bar's payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn into_Bar(self) -> roc_std::U128 {
|
|
self.variant.Bar
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Bar and return its payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn as_Bar(&self) -> roc_std::U128 {
|
|
self.variant.Bar
|
|
}
|
|
|
|
/// Construct a tag named Baz
|
|
pub fn Baz() -> Self {
|
|
Self {
|
|
tag: tag_NonRecursive::Baz,
|
|
variant: unsafe {
|
|
core::mem::transmute::<
|
|
core::mem::MaybeUninit<union_NonRecursive>,
|
|
union_NonRecursive,
|
|
>(core::mem::MaybeUninit::uninit())
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Other `into_` methods return a payload, but since the Baz tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub fn into_Baz(self) {
|
|
()
|
|
}
|
|
|
|
/// Other `as` methods return a payload, but since the Baz tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub unsafe fn as_Baz(&self) {
|
|
()
|
|
}
|
|
|
|
/// Construct a tag named Blah, with the appropriate payload
|
|
pub fn Blah(payload: i32) -> Self {
|
|
Self {
|
|
tag: tag_NonRecursive::Blah,
|
|
variant: union_NonRecursive {
|
|
Blah: payload
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Blah and convert it to Blah's payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn into_Blah(self) -> i32 {
|
|
self.variant.Blah
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Blah and return its payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn as_Blah(&self) -> i32 {
|
|
self.variant.Blah
|
|
}
|
|
|
|
/// Construct a tag named Foo, with the appropriate payload
|
|
pub fn Foo(payload: roc_std::RocStr) -> Self {
|
|
Self {
|
|
tag: tag_NonRecursive::Foo,
|
|
variant: union_NonRecursive {
|
|
Foo: core::mem::ManuallyDrop::new(payload)
|
|
},
|
|
}
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Foo and convert it to Foo's payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn into_Foo(mut self) -> roc_std::RocStr {
|
|
core::mem::ManuallyDrop::take(&mut self.variant.Foo)
|
|
}
|
|
|
|
/// Unsafely assume the given NonRecursive has a .tag() of Foo and return its payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn as_Foo(&self) -> &roc_std::RocStr {
|
|
&self.variant.Foo
|
|
}
|
|
}
|
|
|
|
impl Drop for NonRecursive {
|
|
fn drop(&mut self) {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => {}
|
|
tag_NonRecursive::Baz => {}
|
|
tag_NonRecursive::Blah => {}
|
|
tag_NonRecursive::Foo => unsafe { core::mem::ManuallyDrop::drop(&mut self.variant.Foo) },
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PartialEq for NonRecursive {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
if self.tag != other.tag {
|
|
return false;
|
|
}
|
|
|
|
unsafe {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => self.variant.Bar == other.variant.Bar,
|
|
tag_NonRecursive::Baz => true,
|
|
tag_NonRecursive::Blah => self.variant.Blah == other.variant.Blah,
|
|
tag_NonRecursive::Foo => self.variant.Foo == other.variant.Foo,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Eq for NonRecursive {}
|
|
|
|
impl PartialOrd for NonRecursive {
|
|
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
|
match self.tag.partial_cmp(&other.tag) {
|
|
Some(core::cmp::Ordering::Equal) => {}
|
|
not_eq => return not_eq,
|
|
}
|
|
|
|
unsafe {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => self.variant.Bar.partial_cmp(&other.variant.Bar),
|
|
tag_NonRecursive::Baz => Some(core::cmp::Ordering::Equal),
|
|
tag_NonRecursive::Blah => self.variant.Blah.partial_cmp(&other.variant.Blah),
|
|
tag_NonRecursive::Foo => self.variant.Foo.partial_cmp(&other.variant.Foo),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Ord for NonRecursive {
|
|
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
|
match self.tag.cmp(&other.tag) {
|
|
core::cmp::Ordering::Equal => {}
|
|
not_eq => return not_eq,
|
|
}
|
|
|
|
unsafe {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => self.variant.Bar.cmp(&other.variant.Bar),
|
|
tag_NonRecursive::Baz => core::cmp::Ordering::Equal,
|
|
tag_NonRecursive::Blah => self.variant.Blah.cmp(&other.variant.Blah),
|
|
tag_NonRecursive::Foo => self.variant.Foo.cmp(&other.variant.Foo),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Clone for NonRecursive {
|
|
fn clone(&self) -> Self {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => Self {
|
|
variant: union_NonRecursive {
|
|
Bar: unsafe { self.variant.Bar.clone() },
|
|
},
|
|
tag: tag_NonRecursive::Bar,
|
|
},
|
|
tag_NonRecursive::Baz => Self {
|
|
variant: unsafe {
|
|
core::mem::transmute::<
|
|
core::mem::MaybeUninit<union_NonRecursive>,
|
|
union_NonRecursive,
|
|
>(core::mem::MaybeUninit::uninit())
|
|
},
|
|
tag: tag_NonRecursive::Baz,
|
|
},
|
|
tag_NonRecursive::Blah => Self {
|
|
variant: union_NonRecursive {
|
|
Blah: unsafe { self.variant.Blah.clone() },
|
|
},
|
|
tag: tag_NonRecursive::Blah,
|
|
},
|
|
tag_NonRecursive::Foo => Self {
|
|
variant: union_NonRecursive {
|
|
Foo: unsafe { self.variant.Foo.clone() },
|
|
},
|
|
tag: tag_NonRecursive::Foo,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl core::fmt::Debug for NonRecursive {
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
f.write_str("NonRecursive::")?;
|
|
|
|
unsafe {
|
|
match self.tag {
|
|
tag_NonRecursive::Bar => f.debug_tuple("Bar").field(&self.variant.Bar).finish(),
|
|
tag_NonRecursive::Baz => f.write_str("Baz"),
|
|
tag_NonRecursive::Blah => f.debug_tuple("Blah").field(&self.variant.Blah).finish(),
|
|
tag_NonRecursive::Foo => f.debug_tuple("Foo").field(&self.variant.Foo).finish(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn tag_union_enumeration() {
|
|
let module = indoc!(
|
|
r#"
|
|
NonRecursive : [ Blah, Foo, Bar, ]
|
|
|
|
main : NonRecursive
|
|
main = Foo
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(u8)]
|
|
pub enum NonRecursive {
|
|
Bar = 0,
|
|
Blah = 1,
|
|
Foo = 2,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn single_tag_union_with_payloads() {
|
|
let module = indoc!(
|
|
r#"
|
|
UserId : [ Id U32 Str ]
|
|
|
|
main : UserId
|
|
main = Id 42 "blah"
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Debug, Default, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct UserId {
|
|
pub f1: roc_std::RocStr,
|
|
pub f0: u32,
|
|
}
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn single_tag_union_with_one_payload_field() {
|
|
let module = indoc!(
|
|
r#"
|
|
UserId : [ Id Str ]
|
|
|
|
main : UserId
|
|
main = Id "blah"
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Debug, Default, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(transparent)]
|
|
pub struct UserId(roc_std::RocStr);
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn cons_list_of_strings() {
|
|
let module = indoc!(
|
|
r#"
|
|
StrConsList : [ Nil, Cons Str StrConsList ]
|
|
|
|
main : StrConsList
|
|
main = Cons "Hello, " (Cons "World!" Nil)
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(u8)]
|
|
pub enum tag_StrConsList {
|
|
Cons = 0,
|
|
Nil = 1,
|
|
}
|
|
|
|
#[derive(Clone, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct StrConsList {
|
|
pointer: *mut core::mem::ManuallyDrop<roc_std::RocStr>,
|
|
}
|
|
|
|
impl StrConsList {
|
|
pub fn tag(&self) -> tag_StrConsList {
|
|
if self.pointer.is_null() {
|
|
tag_StrConsList::Nil
|
|
} else {
|
|
tag_StrConsList::Cons
|
|
}
|
|
}
|
|
|
|
/// Construct a tag named Cons, with the appropriate payload
|
|
pub fn Cons(payload: roc_std::RocStr) -> Self {
|
|
let size = core::mem::size_of::<roc_std::RocStr>();
|
|
let align = core::mem::align_of::<roc_std::RocStr>();
|
|
|
|
unsafe {
|
|
let pointer = crate::roc_alloc(size, align as u32) as *mut core::mem::ManuallyDrop<roc_std::RocStr>;
|
|
|
|
*pointer = core::mem::ManuallyDrop::new(payload);
|
|
|
|
Self { pointer }
|
|
}
|
|
}
|
|
|
|
/// Unsafely assume the given StrConsList has a .tag() of Cons and convert it to Cons's payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn into_Cons(self) -> roc_std::RocStr {
|
|
let payload = core::mem::ManuallyDrop::take(&mut *self.pointer);
|
|
let align = core::mem::align_of::<roc_std::RocStr>() as u32;
|
|
|
|
crate::roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
|
|
|
|
payload
|
|
}
|
|
|
|
/// Unsafely assume the given StrConsList has a .tag() of Cons and return its payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn as_Cons(&self) -> &roc_std::RocStr {
|
|
&*self.pointer
|
|
}
|
|
|
|
/// Construct a tag named Nil
|
|
pub fn Nil() -> Self {
|
|
Self {
|
|
pointer: core::ptr::null_mut(),
|
|
}
|
|
}
|
|
|
|
/// Other `into_` methods return a payload, but since the Nil tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub fn into_Nil(self) {
|
|
()
|
|
}
|
|
|
|
/// Other `as` methods return a payload, but since the Nil tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub unsafe fn as_Nil(&self) {
|
|
()
|
|
}
|
|
}
|
|
|
|
impl Drop for StrConsList {
|
|
fn drop(&mut self) {
|
|
if !self.pointer.is_null() {
|
|
let payload = unsafe { &*self.pointer };
|
|
let align = core::mem::align_of::<roc_std::RocStr>() as u32;
|
|
|
|
unsafe {
|
|
crate::roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
|
|
}
|
|
|
|
drop(payload);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl core::fmt::Debug for StrConsList {
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
if self.pointer.is_null() {
|
|
f.write_str("StrConsList::Nil")
|
|
} else {
|
|
f.write_str("StrConsList::")?;
|
|
|
|
unsafe { f.debug_tuple("Cons").field(&**self.pointer).finish() }
|
|
}
|
|
}
|
|
}
|
|
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn cons_list_of_ints() {
|
|
let module = indoc!(
|
|
r#"
|
|
IntConsList : [ Empty, Prepend U16 IntConsList ]
|
|
|
|
main : IntConsList
|
|
main = Prepend 42 (Prepend 26 Empty)
|
|
"#
|
|
);
|
|
|
|
assert_eq!(
|
|
generate_bindings(module)
|
|
.strip_prefix('\n')
|
|
.unwrap_or_default(),
|
|
indoc!(
|
|
r#"
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(u8)]
|
|
pub enum tag_IntConsList {
|
|
Empty = 0,
|
|
Prepend = 1,
|
|
}
|
|
|
|
#[derive(Clone, Eq, Ord, Hash, PartialEq, PartialOrd)]
|
|
#[repr(C)]
|
|
pub struct IntConsList {
|
|
pointer: *mut u16,
|
|
}
|
|
|
|
impl IntConsList {
|
|
pub fn tag(&self) -> tag_IntConsList {
|
|
if self.pointer.is_null() {
|
|
tag_IntConsList::Empty
|
|
} else {
|
|
tag_IntConsList::Prepend
|
|
}
|
|
}
|
|
|
|
/// Construct a tag named Prepend, with the appropriate payload
|
|
pub fn Prepend(payload: u16) -> Self {
|
|
let size = core::mem::size_of::<u16>();
|
|
let align = core::mem::align_of::<u16>();
|
|
|
|
unsafe {
|
|
let pointer = crate::roc_alloc(size, align as u32) as *mut u16;
|
|
|
|
*pointer = payload;
|
|
|
|
Self { pointer }
|
|
}
|
|
}
|
|
|
|
/// Unsafely assume the given IntConsList has a .tag() of Prepend and convert it to Prepend's payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn into_Prepend(self) -> u16 {
|
|
let payload = *self.pointer;
|
|
let align = core::mem::align_of::<u16>() as u32;
|
|
|
|
crate::roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
|
|
|
|
payload
|
|
}
|
|
|
|
/// Unsafely assume the given IntConsList has a .tag() of Prepend and return its payload.
|
|
/// (always examine .tag() first to make sure this is the correct variant!)
|
|
pub unsafe fn as_Prepend(&self) -> u16 {
|
|
*self.pointer
|
|
}
|
|
|
|
/// Construct a tag named Empty
|
|
pub fn Empty() -> Self {
|
|
Self {
|
|
pointer: core::ptr::null_mut(),
|
|
}
|
|
}
|
|
|
|
/// Other `into_` methods return a payload, but since the Empty tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub fn into_Empty(self) {
|
|
()
|
|
}
|
|
|
|
/// Other `as` methods return a payload, but since the Empty tag
|
|
/// has no payload, this does nothing and is only here for completeness.
|
|
pub unsafe fn as_Empty(&self) {
|
|
()
|
|
}
|
|
}
|
|
|
|
impl Drop for IntConsList {
|
|
fn drop(&mut self) {
|
|
if !self.pointer.is_null() {
|
|
let payload = unsafe { &*self.pointer };
|
|
let align = core::mem::align_of::<u16>() as u32;
|
|
|
|
unsafe {
|
|
crate::roc_dealloc(self.pointer as *mut core::ffi::c_void, align);
|
|
}
|
|
|
|
drop(payload);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl core::fmt::Debug for IntConsList {
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
if self.pointer.is_null() {
|
|
f.write_str("IntConsList::Empty")
|
|
} else {
|
|
f.write_str("IntConsList::")?;
|
|
|
|
unsafe { f.debug_tuple("Prepend").field(&*self.pointer).finish() }
|
|
}
|
|
}
|
|
}
|
|
|
|
"#
|
|
)
|
|
);
|
|
}
|
|
}
|