pub type int = i64;
pub type int8 = i8;
pub type int16 = i16;
pub type int32 = i32;
pub type int64 = i64;
pub type uint = u64;
pub type uint8 = u8;
pub type uint16 = u16;
pub type uint32 = u32;
pub type uint64 = u64;
pub type float32 = f32;
pub type float64 = f64;
pub type byte = u8;
pub type rune = i32;
pub type string = crate::gostring::GoString;
pub use crate::_slice::slice;
pub type map<K, V> = std::collections::HashMap<K, V>;
#[macro_export]
macro_rules! slice {
([] int { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::int ),* ]) };
([] int8 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::int8 ),* ]) };
([] int16 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::int16 ),* ]) };
([] int32 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::int32 ),* ]) };
([] int64 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::int64 ),* ]) };
([] uint { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::uint ),* ]) };
([] uint8 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::uint8 ),* ]) };
([] uint16 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::uint16 ),* ]) };
([] uint32 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::uint32 ),* ]) };
([] uint64 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::uint64 ),* ]) };
([] float32 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::float32 ),* ]) };
([] float64 { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::float64 ),* ]) };
([] byte { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::byte ),* ]) };
([] rune { $($x:expr),* $(,)? }) => { $crate::_slice::slice(vec![ $( ($x) as $crate::types::rune ),* ]) };
([] $t:ty { $($x:expr),* $(,)? }) => {
{
let v: $crate::types::slice<$t> =
vec![ $( <$t as ::std::convert::From<_>>::from($x) ),* ].into();
v
}
};
($t:ty ; $($x:expr),* $(,)?) => {
{
let v: $crate::types::slice<$t> =
vec![ $( <$t as ::std::convert::From<_>>::from($x) ),* ].into();
v
}
};
($($x:expr),* $(,)?) => {
{
let v: $crate::types::slice<_> = vec![ $($x),* ].into();
v
}
};
}
#[macro_export]
macro_rules! range {
($iter:expr) => {
$crate::range::RangeIter::range(&$iter)
};
($iter:expr, |$i:pat_param, $v:pat_param| $body:block) => {
for ($i, $v) in $crate::range::RangeIter::range($iter) {
$body
}
};
($iter:expr, |$v:pat_param| $body:block) => {
for $v in ($iter).into_iter() {
$body
}
};
}
#[macro_export]
macro_rules! delete {
($m:expr, $k:expr) => {
{ let _ = ($m).remove($k); }
};
}
#[macro_export]
macro_rules! IntNewtype {
($name:ident = $t:ty) => {
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct $name(pub $t);
impl ::std::convert::From<i32> for $name { fn from(x: i32) -> Self { $name(x as $t) } }
impl ::std::convert::From<i64> for $name { fn from(x: i64) -> Self { $name(x as $t) } }
impl ::std::convert::From<u32> for $name { fn from(x: u32) -> Self { $name(x as $t) } }
impl ::std::convert::From<u64> for $name { fn from(x: u64) -> Self { $name(x as $t) } }
impl ::std::convert::From<usize> for $name { fn from(x: usize) -> Self { $name(x as $t) } }
impl ::std::convert::From<$name> for $t { fn from(x: $name) -> $t { x.0 } }
};
}
#[macro_export]
macro_rules! len {
($x:expr) => {
($x).len() as $crate::types::int
};
}
#[macro_export]
macro_rules! append {
($s:expr $(, $x:expr)+ $(,)?) => {
{
let mut __s = $s;
$( __s.push(($x).into()); )+
__s
}
};
}
#[doc(hidden)]
pub fn __goish_len<N>(n: N) -> usize
where
N: TryInto<usize> + Copy + std::fmt::Display,
<N as TryInto<usize>>::Error: std::fmt::Debug,
{
n.try_into()
.unwrap_or_else(|_| panic!("make: length {} out of range", n))
}
#[macro_export]
macro_rules! make {
(chan $t:ty) => {
$crate::chan::Chan::<$t>::new(0)
};
(chan $t:ty, $cap:expr) => {
$crate::chan::Chan::<$t>::new($crate::types::__goish_len($cap))
};
(map [$k:ty] $v:ty) => {
{
let m: $crate::types::map<$k, $v> = ::std::collections::HashMap::new();
m
}
};
([] $t:ty, 0, $cap:expr) => {
{
let v: $crate::types::slice<$t> =
Vec::<$t>::with_capacity($crate::types::__goish_len($cap)).into();
v
}
};
([] $t:ty, $len:expr, $cap:expr) => {
{
let mut __v: Vec<$t> = Vec::with_capacity($crate::types::__goish_len($cap));
__v.resize_with(
$crate::types::__goish_len($len),
<$t as ::std::default::Default>::default,
);
let v: $crate::types::slice<$t> = __v.into();
v
}
};
([] $t:ty, 0) => {
{
let v: $crate::types::slice<$t> = Vec::<$t>::new().into();
v
}
};
([] $t:ty, $n:expr) => {
{
let v: $crate::types::slice<$t> = vec![
<$t as ::std::default::Default>::default();
$crate::types::__goish_len($n)
].into();
v
}
};
}
#[macro_export]
macro_rules! map {
([$k:ty] $v:ty { $($key:expr => $val:expr),* $(,)? }) => {
{
let mut m: $crate::types::map<$k, $v> = ::std::collections::HashMap::new();
$( m.insert(
<$k as ::std::convert::From<_>>::from($key),
<$v as ::std::convert::From<_>>::from($val),
); )*
m
}
};
($($key:expr => $val:expr),* $(,)?) => {
{
let mut m = ::std::collections::HashMap::new();
$( m.insert($key, $val); )*
m
}
};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slice_untyped_is_vec() {
let v = crate::slice![1, 2, 3];
assert_eq!(v, vec![1, 2, 3]);
}
#[test]
fn slice_typed_string_from_str_literals() {
let v: slice<string> = crate::slice![string; "a", "b", "c"];
assert_eq!(v, vec!["a".to_string(), "b".to_string(), "c".to_string()]);
}
#[test]
fn slice_typed_int64_widens() {
let v: slice<int64> = crate::slice![int64; 1i32, 2i32, 3i32];
assert_eq!(v, vec![1i64, 2i64, 3i64]);
}
#[test]
fn slice_go_shaped_string() {
let v = crate::slice!([]string{"a", "b", "c"});
assert_eq!(v, vec!["a".to_string(), "b".to_string(), "c".to_string()]);
}
#[test]
fn slice_go_shaped_int() {
let v = crate::slice!([]int{1i32, 2i32, 3i32});
assert_eq!(v, vec![1i64, 2i64, 3i64]);
}
#[test]
fn map_go_shaped_string_to_int() {
let m: map<string, int> = crate::map!([string]int{"a" => 1i32, "b" => 2i32});
assert_eq!(m.get("a"), Some(&1i64));
assert_eq!(m.get("b"), Some(&2i64));
assert_eq!(m.len(), 2);
}
#[test]
fn map_go_shaped_string_to_string() {
let m = crate::map!([string]string{"host" => "db", "port" => "5432"});
assert_eq!(m.get("host"), Some(&string::from("db")));
}
#[test]
fn map_inferred_no_conversion() {
let m = crate::map!{1i64 => string::from("a"), 2i64 => string::from("b")};
assert_eq!(m.get(&1), Some(&string::from("a")));
}
#[test]
fn make_empty_map() {
let m = crate::make!(map[string]int);
assert_eq!(m.len(), 0);
}
#[test]
fn make_slice_with_len() {
let v = crate::make!([]int, 5);
assert_eq!(v, vec![0i64, 0, 0, 0, 0]);
assert_eq!(v.len(), 5);
}
#[test]
fn make_slice_with_len_and_cap() {
let v = crate::make!([]int, 0, 10);
assert_eq!(v.len(), 0);
assert!(v.capacity() >= 10);
}
#[test]
fn len_polymorphic() {
let s: string = "hello".into();
assert_eq!(crate::len!(s), 5);
assert_eq!(crate::len!("world"), 5);
let v: slice<int> = crate::slice!([]int{1, 2, 3, 4});
assert_eq!(crate::len!(v), 4);
let m: map<string, int> = crate::map!([string]int{"a" => 1, "b" => 2});
assert_eq!(crate::len!(m), 2);
let ch = crate::chan!(int, 4);
ch.Send(10);
ch.Send(20);
assert_eq!(crate::len!(ch), 2);
}
#[test]
fn append_variadic() {
let s = crate::slice!([]int{1, 2, 3});
let s = crate::append!(s, 4, 5);
assert_eq!(s, vec![1i64, 2, 3, 4, 5]);
}
#[test]
fn append_widens_via_into() {
let s = crate::slice!([]string{"a"});
let s = crate::append!(s, "b", "c"); let want: Vec<string> = vec!["a".into(), "b".into(), "c".into()];
assert_eq!(s, want);
let s: slice<int> = crate::slice!([]int{1});
let s = crate::append!(s, 2i32, 3i32); assert_eq!(s, vec![1i64, 2, 3]);
}
#[test]
fn delete_removes_string_key_literal() {
let mut m: map<string, int> = crate::map!([string]int{"a" => 1, "b" => 2});
crate::delete!(m, "a");
assert_eq!(m.len(), 1);
assert!(!m.contains_key("a"));
assert!(m.contains_key("b"));
}
#[test]
fn delete_with_owned_string_via_ref() {
let mut m: map<string, int> = crate::map!([string]int{"a" => 1});
crate::delete!(m, "a");
assert_eq!(m.len(), 0);
}
#[test]
fn delete_int_key_via_ref() {
let mut m: map<int, string> = crate::map!{1i64 => "a".into(), 2i64 => "b".into()};
crate::delete!(m, &1);
assert_eq!(m.len(), 1);
assert!(m.contains_key(&2));
}
#[test]
fn make_slice_accepts_int_len() {
let l: int = 5;
let v = crate::make!([]int, l);
assert_eq!(v.len(), 5);
let u: usize = 3;
let v = crate::make!([]int, u);
assert_eq!(v.len(), 3);
}
#[test]
#[should_panic(expected = "out of range")]
fn make_slice_negative_len_panics() {
let l: int = -1;
let _ = crate::make!([]int, l);
}
#[test]
fn make_slice_len_cap_accepts_int() {
let l: int = 2;
let c: int = 10;
let v = crate::make!([]int, l, c);
assert_eq!(v.len(), 2);
assert!(v.capacity() >= 10);
}
#[test]
fn int_newtype_macro() {
use crate as goish;
goish::IntNewtype!(ID = u64);
let ids: crate::types::slice<ID> = crate::slice!([]ID{10i32, 20i32, 30i32});
assert_eq!(ids[0i64].0, 10u64);
assert_eq!(ids[2i64].0, 30u64);
let u: u64 = ID(42).into();
assert_eq!(u, 42);
assert_eq!(ID(1), ID(1));
assert!(ID(1) < ID(2));
}
#[test]
fn delete_missing_key_is_noop() {
let mut m: map<string, int> = crate::map!([string]int{"a" => 1});
crate::delete!(m, "missing");
assert_eq!(m.len(), 1);
}
}