///|
impl FromSexp with sexp_path_key(_) {
None
}
///|
pub impl FromSexp for Symbol with sexp_path_key(key) {
Some(key)
}
///|
pub impl ToSexp for Int with to_sexp(self) {
Int(self)
}
///|
pub impl FromSexp for Int with from_sexp(sexp, path) {
match sexp {
Int(n) => n
_ => raise SexpError("Int::from_sexp: Expected Int", path)
}
}
///|
pub impl ToSexp for UInt with to_sexp(self) {
String(self.to_string())
}
///|
pub impl FromSexp for UInt with from_sexp(sexp, path) {
guard sexp is String(str) else {
raise SexpError("UInt::from_sexp: Expected number in string representation", path)
}
@strconv.parse_uint(str) catch {
error => raise SexpError("UInt::from_sexp: UInt parsing failure \{error}", path)
}
}
///|
pub impl ToSexp for Int64 with to_sexp(self) {
String(self.to_string())
}
///|
pub impl FromSexp for Int64 with from_sexp(sexp, path) {
guard sexp is String(str) else {
raise SexpError("Int64::from_sexp: Expected number in string representation", path)
}
@strconv.parse_int64(str) catch {
error => raise SexpError("Int64::from_sexp: Int64 parsing failure \{error}", path)
}
}
///|
pub impl ToSexp for UInt64 with to_sexp(self) {
String(self.to_string())
}
///|
pub impl FromSexp for UInt64 with from_sexp(sexp, path) {
guard sexp is String(str) else {
raise SexpError("UInt64::from_sexp: Expected number in string representation", path)
}
@strconv.parse_uint64(str) catch {
error => raise SexpError("UInt64::from_sexp: UInt64 parsing failure \{error}", path)
}
}
///|
pub impl ToSexp for Double with to_sexp(self) {
Double(self)
}
///|
pub impl FromSexp for Double with from_sexp(sexp, path) {
match sexp {
Double(n) => n
Int(i) => i.to_double()
_ => raise SexpError("Double::from_sexp: Expected Double", path)
}
}
///|
pub impl ToSexp for Float with to_sexp(self) {
Double(self.to_double())
}
///|
pub impl FromSexp for Float with from_sexp(sexp, path) {
match sexp {
Double(n) => Float::from_double(n)
Int(i) => Float::from_double(i.to_double())
_ => raise SexpError("Float::from_sexp: Expected Double", path)
}
}
///|
pub impl ToSexp for Bool with to_sexp(self) {
Bool(self)
}
///|
pub impl FromSexp for Bool with from_sexp(sexp, path) {
match sexp {
Bool(b) => b
_ => raise SexpError("Bool::from_sexp: Expected Bool", path)
}
}
///|
pub impl ToSexp for Char with to_sexp(self) {
Sexp::Char(self)
}
///|
pub impl FromSexp for Char with from_sexp(sexp, path) {
match sexp {
Char(c) => c
_ => raise SexpError("Char::from_sexp: Expected Char", path)
}
}
///|
pub impl ToSexp for String with to_sexp(self) {
String(self)
}
///|
pub impl FromSexp for String with from_sexp(sexp, path) {
match sexp {
String(s) => s
_ => raise SexpError("String::from_sexp: Expected String", path)
}
}
///|
pub impl ToSexp for StringView with to_sexp(self) {
String(self.to_string())
}
///|
pub impl FromSexp for StringView with from_sexp(sexp, path) {
(FromSexp::from_sexp(sexp, path) : String)
}
///|
pub impl FromSexp for Symbol with from_sexp(sexp, path) {
match sexp {
Symbol(s) => s
_ => raise SexpError("Symbol::from_sexp: Expected Symbol", path)
}
}
///|
pub impl ToSexp for Symbol with to_sexp(self) {
Symbol(self)
}
///|
pub impl FromSexp for Unit with from_sexp(sexp, path) {
match sexp {
List(xs) if xs.length() == 0 => ()
_ => raise SexpError("Unit::from_sexp: Expected empty list", path)
}
}
///|
pub impl ToSexp for Unit with to_sexp(_) {
List([])
}
///|
pub impl[T : ToSexp] ToSexp for ArrayView[T] with to_sexp(self) {
Sexp::List(self.map(fn(x) { x.to_sexp() }))
}
///|
pub impl[T : FromSexp] FromSexp for ArrayView[T] with from_sexp(sexp, path) {
(FromSexp::from_sexp(sexp, path) : Array[T])
}
///|
pub impl[T : ToSexp] ToSexp for Array[T] with to_sexp(self) {
ToSexp::to_sexp(self[:])
}
///|
pub impl[T : FromSexp] FromSexp for Array[T] with from_sexp(sexp, path) {
match sexp {
List(xs) => {
let arr = []
for i = 0; i < xs.length(); i = i + 1 {
arr.push(T::from_sexp(xs[i], path.add_index(i)))
}
arr
}
_ => raise SexpError("Array::from_sexp: Expected List", path)
}
}
///|
pub impl[T : ToSexp] ToSexp for FixedArray[T] with to_sexp(self) {
Array::from_fixed_array(self) |> ToSexp::to_sexp
}
///|
pub impl[T : FromSexp] FromSexp for FixedArray[T] with from_sexp(sexp, path) {
FromSexp::from_sexp(sexp, path) |> FixedArray::from_array
}
///|
pub impl[T : ToSexp, U : ToSexp] ToSexp for (T, U) with to_sexp(self) {
List([self.0.to_sexp(), self.1.to_sexp()])
}
///|
pub impl[T : FromSexp, U : FromSexp] FromSexp for (T, U) with from_sexp(
sexp,
path,
) {
match sexp {
List(xs) if xs.length() == 2 =>
(
T::from_sexp(xs[0], path.add_index(0)),
U::from_sexp(xs[1], path.add_index(1)),
)
_ => raise SexpError("Tuple::from_sexp: Expected List of length 2", path)
}
}
///|
pub impl[T : ToSexp] ToSexp for T? with to_sexp(self) {
match self {
Some(value) => List([value.to_sexp()])
None => List([])
}
}
///|
pub impl[T : FromSexp] FromSexp for T? with from_sexp(sexp, path) {
match sexp {
List([]) => None
List([x]) => Some(T::from_sexp(x, path.add_index(0)))
_ => raise SexpError("Option::from_sexp: Expected List of length 0 or 1", path)
}
}
///|
pub impl[T : ToSexp, E : ToSexp] ToSexp for Result[T, E] with to_sexp(self) {
match self {
Ok(value) => List([Symbol(Symbol::new("ok")), value.to_sexp()])
Err(err) => List([Symbol(Symbol::new("err")), err.to_sexp()])
}
}
///|
pub impl[T : FromSexp, E : FromSexp] FromSexp for Result[T, E] with from_sexp(
sexp,
path,
) {
guard sexp is List([tag, value]) else {
raise SexpError("Result::from_sexp: Expected List of length 2", path)
}
guard tag is Symbol(sym) else {
raise SexpError("Result::from_sexp: Expected Symbol tag", path.add_index(0))
}
match sym.to_string() {
"ok" => Ok(T::from_sexp(value, path.add_key(sym)))
"err" => Err(E::from_sexp(value, path.add_key(sym)))
_ =>
raise SexpError(
"Result::from_sexp: Expected 'ok' or 'err' tag",
path.add_index(0),
)
}
}
///|
pub impl[K : ToSexp, V : ToSexp] ToSexp for Map[K, V] with to_sexp(self) {
let entries = []
for key, value in self {
entries.push(List([key.to_sexp(), value.to_sexp()]))
}
List(entries)
}
///|
pub impl[K : FromSexp + Eq + Hash, V : FromSexp] FromSexp for Map[K, V] with from_sexp(
sexp,
path,
) {
match sexp {
List(xs) => {
let map = {}
for i = 0; i < xs.length(); i = i + 1 {
match xs[i] {
List(entry) if entry.length() == 2 => {
let key = K::from_sexp(entry[0], path.add_index(i).add_index(0))
let value = match key.sexp_path_key() {
Some(sym) => V::from_sexp(entry[1], path.add_key(sym))
None => V::from_sexp(entry[1], path.add_index(i).add_index(1))
}
map[key] = value
}
_ =>
raise SexpError(
"Map::from_sexp: Expected List of length 2 for entry",
path.add_index(i),
)
}
}
map
}
_ => raise SexpError("Map::from_sexp: Expected List", path)
}
}
///|
pub impl ToSexp for BytesView with to_sexp(self) {
let sb = StringBuilder::new()
for byte in self {
if byte is (' '..='~') && byte != '"' && byte != '\\' {
sb.write_char(byte.to_char())
} else {
sb..write_string("\\x")..write_string(byte.to_hex())
}
}
String(sb.to_string())
}
///|
pub impl FromSexp for BytesView with from_sexp(sexp, path) {
(FromSexp::from_sexp(sexp, path) : Bytes)
}
///|
pub impl ToSexp for Bytes with to_sexp(self) {
ToSexp::to_sexp(self[:])
}
// Copied from core/json/from_json.mbt
///|
pub impl FromSexp for Bytes with from_sexp(sexp, path) {
guard sexp is String(a) else {
raise SexpError("Bytes::from_sexp: Expected string", path)
}
let buffer = @buffer.new(size_hint=a.length())
loop a[:] {
[] => ()
[.. "\\x", '0'..='9' | 'a'..='f' as x, '0'..='9' | 'a'..='f' as y, .. rest] => {
let upper = (x.to_int() & 0xF) + (x.to_int() >> 6) * 9
let lower = (y.to_int() & 0xF) + (y.to_int() >> 6) * 9
buffer.write_byte(((upper << 4) | lower).to_byte())
continue rest
}
[' '..='~' as ch, .. rest] => {
guard ch != '\\' && ch != '"' else {
raise SexpError("Bytes::from_sexp: Invalid escape sequence", path)
}
buffer.write_byte(ch.to_uint().to_byte())
continue rest
}
_ => raise SexpError("Bytes::from_sexp: Invalid byte sequence", path)
}
buffer.to_bytes()
}
///|
pub impl ToSexp for Sexp with to_sexp(self) {
self
}
///|
pub impl FromSexp for Sexp with from_sexp(sexp, _) {
sexp
}