use crate::{
de::{DeserializeSeed, Error, Kind, Result},
ArrayAccess, BignumRef, Deserialize, DeserializerTrait, Fixnum, HashAccess, Instance,
InstanceAccess, IvarAccess, Object, RbFields, RbHash, RbString, Sym, Userdata, Value, Visitor,
VisitorInstance, VisitorOption,
};
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = Value;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("any ruby value")
}
fn visit_nil(self) -> Result<Self::Value> {
Ok(Value::Nil)
}
fn visit_bool(self, v: bool) -> Result<Self::Value> {
Ok(Value::Bool(v))
}
fn visit_fixnum(self, v: Fixnum) -> Result<Self::Value> {
Ok(Value::Fixnum(v))
}
fn visit_bignum(self, v: BignumRef<'de>) -> Result<Self::Value> {
Ok(Value::Bignum(v.into()))
}
fn visit_f64(self, v: f64) -> Result<Self::Value> {
Ok(Value::Float(v))
}
fn visit_hash<A>(self, mut map: A) -> Result<Self::Value>
where
A: HashAccess<'de>,
{
let mut hash = RbHash::with_capacity(map.len());
while let Some((k, v)) = map.next_entry()? {
hash.insert(k, v);
}
Ok(Value::Hash(hash))
}
fn visit_array<A>(self, mut access: A) -> Result<Self::Value>
where
A: ArrayAccess<'de>,
{
let mut array = Vec::with_capacity(access.len());
while let Some(v) = access.next_element()? {
array.push(v);
}
Ok(Value::Array(array))
}
fn visit_string(self, string: &'de [u8]) -> Result<Self::Value> {
Ok(Value::String(RbString {
data: string.to_vec(),
}))
}
fn visit_symbol(self, symbol: &'de Sym) -> Result<Self::Value> {
Ok(Value::Symbol(symbol.to_symbol()))
}
fn visit_regular_expression(self, data: &'de [u8], flags: u8) -> Result<Self::Value> {
Ok(Value::Regex {
data: RbString::from(data),
flags,
})
}
fn visit_object<A>(self, class: &'de Sym, mut instance_variables: A) -> Result<Self::Value>
where
A: IvarAccess<'de>,
{
let mut fields = RbFields::with_capacity(instance_variables.len());
while let Some((k, v)) = instance_variables.next_entry()? {
fields.insert(k.to_symbol(), v);
}
Ok(Value::Object(Object {
class: class.to_symbol(),
fields,
}))
}
fn visit_struct<A>(self, name: &'de Sym, mut members: A) -> Result<Self::Value>
where
A: IvarAccess<'de>,
{
let mut fields = RbFields::with_capacity(members.len());
while let Some((k, v)) = members.next_entry()? {
fields.insert(k.to_symbol(), v);
}
Ok(Value::RbStruct(crate::RbStruct {
class: name.to_symbol(),
fields,
}))
}
fn visit_class(self, class: &'de Sym) -> Result<Self::Value> {
Ok(Value::Class(class.to_symbol()))
}
fn visit_module(self, module: &'de Sym) -> Result<Self::Value> {
Ok(Value::Module(module.to_symbol()))
}
fn visit_instance<A>(self, instance: A) -> Result<Self::Value>
where
A: InstanceAccess<'de>,
{
let (value, mut instance_fields) = instance.value()?;
let mut fields = RbFields::with_capacity(instance_fields.len());
while let Some((field, value)) = instance_fields.next_entry()? {
fields.insert(field.to_symbol(), value);
}
let instance = Instance {
value: Box::new(value),
fields,
};
Ok(Value::Instance(instance))
}
fn visit_extended<D>(self, module: &'de Sym, deserializer: D) -> Result<Self::Value>
where
D: DeserializerTrait<'de>,
{
let value = deserializer.deserialize(ValueVisitor)?;
Ok(Value::Extended {
module: module.to_symbol(),
value: Box::new(value),
})
}
fn visit_user_class<D>(self, class: &'de Sym, deserializer: D) -> Result<Self::Value>
where
D: DeserializerTrait<'de>,
{
let value = deserializer.deserialize(ValueVisitor)?;
Ok(Value::UserClass {
class: class.to_symbol(),
value: Box::new(value),
})
}
fn visit_user_data(self, class: &'de Sym, data: &'de [u8]) -> Result<Self::Value> {
Ok(Value::Userdata(Userdata {
class: class.to_symbol(),
data: data.to_vec(),
}))
}
fn visit_user_marshal<D>(self, class: &'de Sym, deserializer: D) -> Result<Self::Value>
where
D: DeserializerTrait<'de>,
{
let value = deserializer.deserialize(ValueVisitor)?;
Ok(Value::UserMarshal {
class: class.to_symbol(),
value: Box::new(value),
})
}
fn visit_data<D>(self, class: &'de Sym, deserializer: D) -> Result<Self::Value>
where
D: DeserializerTrait<'de>,
{
let value = deserializer.deserialize(ValueVisitor)?;
Ok(Value::Data {
class: class.to_symbol(),
value: Box::new(value),
})
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Self>
where
D: DeserializerTrait<'de>,
{
deserializer.deserialize(ValueVisitor)
}
}
struct ValueInstanceAccess<'de> {
value: &'de Value,
fields: &'de RbFields,
}
struct ValueIVarAccess<'de> {
fields: &'de RbFields,
index: usize,
state: MapState,
}
struct ValueArrayAccess<'de> {
array: &'de [Value],
index: usize,
}
struct ValueHashAccess<'de> {
hash: &'de RbHash,
index: usize,
state: MapState,
}
enum MapState {
Key,
Value,
}
impl<'de> DeserializerTrait<'de> for &'de Value {
fn deserialize<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self {
Value::Nil => visitor.visit_nil(),
Value::Bool(v) => visitor.visit_bool(*v),
Value::Float(f) => visitor.visit_f64(*f),
Value::Fixnum(i) => visitor.visit_fixnum(*i),
Value::Bignum(i) => visitor.visit_bignum(i.as_ref()),
Value::String(s) => visitor.visit_string(&s.data),
Value::Symbol(s) => visitor.visit_symbol(s),
Value::Array(array) => visitor.visit_array(ValueArrayAccess { array, index: 0 }),
Value::Hash(hash) => visitor.visit_hash(ValueHashAccess {
hash,
index: 0,
state: MapState::Value, }),
Value::Userdata(u) => visitor.visit_user_data(&u.class, &u.data),
Value::Object(o) => visitor.visit_object(
&o.class,
ValueIVarAccess {
fields: &o.fields,
index: 0,
state: MapState::Value, },
),
Value::Instance(i) => visitor.visit_instance(ValueInstanceAccess {
value: &i.value,
fields: &i.fields,
}),
Value::Regex { data, flags } => visitor.visit_regular_expression(&data.data, *flags),
Value::RbStruct(s) => visitor.visit_struct(
&s.class,
ValueIVarAccess {
fields: &s.fields,
index: 0,
state: MapState::Value, },
),
Value::Class(c) => visitor.visit_class(c),
Value::Module(m) => visitor.visit_module(m),
Value::Extended { module, value } => visitor.visit_extended(module, value.as_ref()),
Value::UserClass { class, value } => visitor.visit_user_class(class, value.as_ref()),
Value::UserMarshal { class, value } => {
visitor.visit_user_marshal(class, value.as_ref())
}
Value::Data { class, value } => visitor.visit_data(class, value.as_ref()),
}
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: VisitorOption<'de>,
{
if matches!(self, Value::Nil) {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_instance<V>(self, visitor: V) -> Result<V::Value>
where
V: VisitorInstance<'de>,
{
if let Value::Instance(i) = self {
visitor.visit_instance(ValueInstanceAccess {
value: &i.value,
fields: &i.fields,
})
} else {
visitor.visit(self)
}
}
}
impl<'de> InstanceAccess<'de> for ValueInstanceAccess<'de> {
type IvarAccess = ValueIVarAccess<'de>;
fn value_seed<V>(self, seed: V) -> Result<(V::Value, Self::IvarAccess)>
where
V: DeserializeSeed<'de>,
{
let value = seed.deserialize(self.value)?;
let access = ValueIVarAccess {
fields: self.fields,
index: 0,
state: MapState::Value, };
Ok((value, access))
}
}
impl<'de> IvarAccess<'de> for ValueIVarAccess<'de> {
fn next_ivar(&mut self) -> Result<Option<&'de Sym>> {
let Some((field, _)) = self.fields.get_index(self.index) else {
return Ok(None);
};
match self.state {
MapState::Key => {
return Err(Error {
kind: Kind::KeyAfterKey,
})
}
MapState::Value => self.state = MapState::Key,
}
Ok(Some(field))
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
let (_, value) = self.fields.get_index(self.index).ok_or(Error {
kind: Kind::ValueAfterValue,
})?;
self.state = MapState::Value;
self.index += 1;
seed.deserialize(value)
}
fn len(&self) -> usize {
self.fields.len()
}
fn index(&self) -> usize {
self.index
}
}
impl<'de> ArrayAccess<'de> for ValueArrayAccess<'de> {
fn next_element_seed<V>(&mut self, seed: V) -> Result<Option<V::Value>>
where
V: DeserializeSeed<'de>,
{
let Some(value) = self.array.get(self.index) else {
return Ok(None);
};
self.index += 1;
seed.deserialize(value).map(Some)
}
fn len(&self) -> usize {
self.array.len()
}
fn index(&self) -> usize {
self.index
}
}
impl<'de> HashAccess<'de> for ValueHashAccess<'de> {
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
let Some((key, _)) = self.hash.get_index(self.index) else {
return Ok(None);
};
match self.state {
MapState::Key => {
return Err(Error {
kind: Kind::KeyAfterKey,
})
}
MapState::Value => self.state = MapState::Key,
}
seed.deserialize(key).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
let (_, value) = self.hash.get_index(self.index).ok_or(Error {
kind: Kind::ValueAfterValue,
})?;
self.state = MapState::Value;
self.index += 1;
seed.deserialize(value)
}
fn len(&self) -> usize {
self.hash.len()
}
fn index(&self) -> usize {
self.index
}
}