mod decode;
mod encode;
mod fold;
mod print_source;
pub use fold::ValueVisitor;
use crate::{boxed, string, vec};
use crate::ir;
use crate::{Error, Result};
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Prim8(u8),
Prim16(u16),
Prim32(u32),
Prim64(u64),
Tuple(vec::Vec<Value>),
Array(vec::Vec<Value>),
Enum(usize, boxed::Box<Value>),
}
impl Value {
pub fn unit() -> Value {
Value::Tuple(vec![])
}
pub fn expect_prim8(&self) -> Result<u8> {
match self {
Value::Prim8(value) => Ok(*value),
_ => Err(Error::BadValueType {
expected: "Prim8",
found: self.name(),
}),
}
}
pub fn expect_prim16(&self) -> Result<u16> {
match self {
Value::Prim16(value) => Ok(*value),
_ => Err(Error::BadValueType {
expected: "Prim16",
found: self.name(),
}),
}
}
pub fn expect_prim32(&self) -> Result<u32> {
match self {
Value::Prim32(value) => Ok(*value),
_ => Err(Error::BadValueType {
expected: "Prim32",
found: self.name(),
}),
}
}
pub fn expect_prim64(&self) -> Result<u64> {
match self {
Value::Prim64(value) => Ok(*value),
_ => Err(Error::BadValueType {
expected: "Prim64",
found: self.name(),
}),
}
}
pub fn new_text(s: &str) -> Value {
Value::Array(s.bytes().map(Value::Prim8).collect())
}
pub fn expect_text_cloned(&self) -> Result<string::String> {
match self {
Value::Array(bytes) => {
let bytes: vec::Vec<u8> = bytes
.iter()
.map(|v| v.expect_prim8())
.collect::<Result<_>>()?;
string::String::from_utf8(bytes).map_err(|_| Error::InvalidData)
}
_ => Err(Error::BadValueType {
expected: "Text",
found: self.name(),
}),
}
}
pub fn expect_tuple(&self) -> Result<&[Value]> {
match self {
Value::Tuple(value) => Ok(value),
_ => Err(Error::BadValueType {
expected: "Tuple",
found: self.name(),
}),
}
}
pub fn expect_array(&self) -> Result<&[Value]> {
match self {
Value::Array(value) => Ok(value),
_ => Err(Error::BadValueType {
expected: "Array",
found: self.name(),
}),
}
}
pub fn expect_enum(&self) -> Result<(usize, &Value)> {
match self {
Value::Enum(tag, inner) => Ok((*tag, inner)),
_ => Err(Error::BadValueType {
expected: "Enum",
found: self.name(),
}),
}
}
fn name(&self) -> &'static str {
match self {
Value::Prim8(..) => "Prim8",
Value::Prim16(..) => "Prim16",
Value::Prim32(..) => "Prim32",
Value::Prim64(..) => "Prim64",
Value::Tuple(..) => "Tuple",
Value::Array(..) => "Array",
Value::Enum(..) => "Enum",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
enum TyClass<'t> {
Prim8,
Prim16,
Prim32,
Prim64,
Tuple(&'t [ir::TyTupleField]),
Array(&'t ir::Ty),
Enum(&'t [ir::TyEnumVariant]),
}
impl<'t> TyClass<'t> {
fn of_ty(ty_mat: &'t ir::Ty) -> Result<Self> {
Ok(match &ty_mat.kind {
ir::TyKind::Primitive(ir::TyPrimitive::Prim8) => TyClass::Prim8,
ir::TyKind::Primitive(ir::TyPrimitive::Prim16) => TyClass::Prim16,
ir::TyKind::Primitive(ir::TyPrimitive::Prim32) => TyClass::Prim32,
ir::TyKind::Primitive(ir::TyPrimitive::Prim64) => TyClass::Prim64,
ir::TyKind::Tuple(t) => TyClass::Tuple(t),
ir::TyKind::Array(t) => TyClass::Array(t),
ir::TyKind::Enum(t) => TyClass::Enum(t),
ir::TyKind::Function(..) => return Err(Error::InvalidType),
ir::TyKind::Ident(..) => return Err(Error::Bug),
})
}
}