use crate::dynamic_value;
use crate::introspect::{Type, TypeVariant};
use crate::private::layout::{self, PrimitiveElement};
use crate::traits::{IndexMove, ListIter};
use crate::{Error, ErrorKind, Result};
#[derive(Copy, Clone)]
pub struct Reader<'a> {
pub(crate) reader: layout::ListReader<'a>,
pub(crate) element_type: Type,
}
impl<'a> From<Reader<'a>> for dynamic_value::Reader<'a> {
fn from(x: Reader<'a>) -> dynamic_value::Reader<'a> {
dynamic_value::Reader::List(x)
}
}
impl<'a> Reader<'a> {
pub(crate) fn new(reader: layout::ListReader<'a>, element_type: Type) -> Self {
Self {
reader,
element_type,
}
}
pub fn len(&self) -> u32 {
self.reader.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn element_type(&self) -> Type {
self.element_type
}
pub fn get(self, index: u32) -> Result<crate::dynamic_value::Reader<'a>> {
assert!(index < self.reader.len());
match self.element_type.which() {
TypeVariant::Void => Ok(dynamic_value::Reader::Void),
TypeVariant::Bool => Ok(dynamic_value::Reader::Bool(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Int8 => Ok(dynamic_value::Reader::Int8(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Int16 => Ok(dynamic_value::Reader::Int16(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Int32 => Ok(dynamic_value::Reader::Int32(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Int64 => Ok(dynamic_value::Reader::Int64(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::UInt8 => Ok(dynamic_value::Reader::UInt8(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::UInt16 => Ok(dynamic_value::Reader::UInt16(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::UInt32 => Ok(dynamic_value::Reader::UInt32(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::UInt64 => Ok(dynamic_value::Reader::UInt64(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Float32 => Ok(dynamic_value::Reader::Float32(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Float64 => Ok(dynamic_value::Reader::Float64(PrimitiveElement::get(
&self.reader,
index,
))),
TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new(
PrimitiveElement::get(&self.reader, index),
e.into(),
)
.into()),
TypeVariant::Text => Ok(dynamic_value::Reader::Text(
self.reader.get_pointer_element(index).get_text(None)?,
)),
TypeVariant::Data => Ok(dynamic_value::Reader::Data(
self.reader.get_pointer_element(index).get_data(None)?,
)),
TypeVariant::List(element_type) => Ok(Reader {
reader: self
.reader
.get_pointer_element(index)
.get_list(element_type.expected_element_size(), None)?,
element_type,
}
.into()),
TypeVariant::Struct(ss) => {
let r = self.reader.get_struct_element(index);
Ok(dynamic_value::Reader::Struct(
crate::dynamic_struct::Reader::new(r, ss.into()),
))
}
TypeVariant::AnyPointer => {
Ok(crate::any_pointer::Reader::new(self.reader.get_pointer_element(index)).into())
}
TypeVariant::Capability => {
Ok(dynamic_value::Reader::Capability(dynamic_value::Capability))
}
}
}
pub fn iter(self) -> ListIter<Reader<'a>, Result<dynamic_value::Reader<'a>>> {
ListIter::new(self, self.len())
}
}
impl<'a> IndexMove<u32, Result<dynamic_value::Reader<'a>>> for Reader<'a> {
fn index_move(&self, index: u32) -> Result<dynamic_value::Reader<'a>> {
self.get(index)
}
}
impl<'a> ::core::iter::IntoIterator for Reader<'a> {
type Item = Result<dynamic_value::Reader<'a>>;
type IntoIter = ListIter<Reader<'a>, Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct Builder<'a> {
pub(crate) builder: layout::ListBuilder<'a>,
pub(crate) element_type: Type,
}
impl<'a> From<Builder<'a>> for dynamic_value::Builder<'a> {
fn from(x: Builder<'a>) -> dynamic_value::Builder<'a> {
dynamic_value::Builder::List(x)
}
}
impl<'a> Builder<'a> {
pub(crate) fn new(builder: layout::ListBuilder<'a>, element_type: Type) -> Self {
Self {
builder,
element_type,
}
}
pub fn reborrow(&mut self) -> Builder<'_> {
Builder {
builder: self.builder.reborrow(),
element_type: self.element_type,
}
}
pub fn into_reader(self) -> Reader<'a> {
Reader {
reader: self.builder.into_reader(),
element_type: self.element_type,
}
}
pub fn len(&self) -> u32 {
self.builder.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn element_type(&self) -> Type {
self.element_type
}
pub fn get(self, index: u32) -> Result<dynamic_value::Builder<'a>> {
assert!(index < self.builder.len());
match self.element_type.which() {
TypeVariant::Void => Ok(dynamic_value::Builder::Void),
TypeVariant::Bool => Ok(dynamic_value::Builder::Bool(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Int8 => Ok(dynamic_value::Builder::Int8(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Int16 => Ok(dynamic_value::Builder::Int16(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Int32 => Ok(dynamic_value::Builder::Int32(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Int64 => Ok(dynamic_value::Builder::Int64(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::UInt8 => Ok(dynamic_value::Builder::UInt8(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::UInt16 => Ok(dynamic_value::Builder::UInt16(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::UInt32 => Ok(dynamic_value::Builder::UInt32(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::UInt64 => Ok(dynamic_value::Builder::UInt64(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Float32 => Ok(dynamic_value::Builder::Float32(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Float64 => Ok(dynamic_value::Builder::Float64(
PrimitiveElement::get_from_builder(&self.builder, index),
)),
TypeVariant::Enum(e) => Ok(dynamic_value::Enum::new(
PrimitiveElement::get_from_builder(&self.builder, index),
e.into(),
)
.into()),
TypeVariant::Text => Ok(dynamic_value::Builder::Text(
self.builder.get_pointer_element(index).get_text(None)?,
)),
TypeVariant::Data => Ok(dynamic_value::Builder::Data(
self.builder.get_pointer_element(index).get_data(None)?,
)),
TypeVariant::List(element_type) => Ok(Builder {
builder: self
.builder
.get_pointer_element(index)
.get_list(element_type.expected_element_size(), None)?,
element_type,
}
.into()),
TypeVariant::Struct(ss) => {
let r = self.builder.get_struct_element(index);
Ok(dynamic_value::Builder::Struct(
crate::dynamic_struct::Builder::new(r, ss.into()),
))
}
TypeVariant::AnyPointer => Ok(crate::any_pointer::Builder::new(
self.builder.get_pointer_element(index),
)
.into()),
TypeVariant::Capability => Ok(dynamic_value::Builder::Capability(
dynamic_value::Capability,
)),
}
}
pub fn set(&mut self, index: u32, value: dynamic_value::Reader<'_>) -> Result<()> {
assert!(index < self.builder.len());
match (self.element_type.which(), value) {
(TypeVariant::Void, _) => Ok(()),
(TypeVariant::Bool, dynamic_value::Reader::Bool(b)) => {
PrimitiveElement::set(&self.builder, index, b);
Ok(())
}
(TypeVariant::Int8, dynamic_value::Reader::Int8(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Int16, dynamic_value::Reader::Int16(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Int32, dynamic_value::Reader::Int32(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Int64, dynamic_value::Reader::Int64(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::UInt8, dynamic_value::Reader::UInt8(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::UInt16, dynamic_value::Reader::UInt16(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::UInt32, dynamic_value::Reader::UInt32(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::UInt64, dynamic_value::Reader::UInt64(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Float32, dynamic_value::Reader::Float32(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Float64, dynamic_value::Reader::Float64(x)) => {
PrimitiveElement::set(&self.builder, index, x);
Ok(())
}
(TypeVariant::Enum(_es), dynamic_value::Reader::Enum(e)) => {
PrimitiveElement::set(&self.builder, index, e.get_value());
Ok(())
}
(TypeVariant::Text, dynamic_value::Reader::Text(t)) => {
self.builder
.reborrow()
.get_pointer_element(index)
.set_text(t);
Ok(())
}
(TypeVariant::Data, dynamic_value::Reader::Data(d)) => {
self.builder
.reborrow()
.get_pointer_element(index)
.set_data(d);
Ok(())
}
(TypeVariant::Struct(ss), dynamic_value::Reader::Struct(s)) => {
assert_eq!(ss, s.get_schema().raw);
self.builder
.reborrow()
.get_struct_element(index)
.copy_content_from(&s.reader)
}
(TypeVariant::List(_element_type), dynamic_value::Reader::List(list)) => self
.builder
.reborrow()
.get_pointer_element(index)
.set_list(&list.reader, false),
(TypeVariant::AnyPointer, _) => {
Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported))
}
(TypeVariant::Capability, dynamic_value::Reader::Capability(_)) => {
Err(Error::from_kind(ErrorKind::ListCapabilityNotSupported))
}
(_, _) => Err(Error::from_kind(ErrorKind::TypeMismatch)),
}
}
pub fn init(self, index: u32, size: u32) -> Result<dynamic_value::Builder<'a>> {
assert!(index < self.builder.len());
match self.element_type.which() {
TypeVariant::Void
| TypeVariant::Bool
| TypeVariant::Int8
| TypeVariant::Int16
| TypeVariant::Int32
| TypeVariant::Int64
| TypeVariant::UInt8
| TypeVariant::UInt16
| TypeVariant::UInt32
| TypeVariant::UInt64
| TypeVariant::Float32
| TypeVariant::Float64
| TypeVariant::Enum(_)
| TypeVariant::Struct(_)
| TypeVariant::Capability => Err(Error::from_kind(ErrorKind::ExpectedAListOrBlob)),
TypeVariant::Text => Ok(self
.builder
.get_pointer_element(index)
.init_text(size)
.into()),
TypeVariant::Data => Ok(self
.builder
.get_pointer_element(index)
.init_data(size)
.into()),
TypeVariant::List(inner_element_type) => match inner_element_type.which() {
TypeVariant::Struct(rbs) => Ok(Builder::new(
self.builder.get_pointer_element(index).init_struct_list(
size,
crate::dynamic_struct::struct_size_from_schema(rbs.into())?,
),
inner_element_type,
)
.into()),
_ => Ok(Builder::new(
self.builder
.get_pointer_element(index)
.init_list(inner_element_type.expected_element_size(), size),
inner_element_type,
)
.into()),
},
TypeVariant::AnyPointer => Err(Error::from_kind(ErrorKind::ListAnyPointerNotSupported)),
}
}
}
impl<'a> crate::traits::SetterInput<crate::any_pointer::Owned> for Reader<'a> {
fn set_pointer_builder<'b>(
mut pointer: crate::private::layout::PointerBuilder<'b>,
value: Reader<'a>,
canonicalize: bool,
) -> Result<()> {
pointer.set_list(&value.reader, canonicalize)
}
}
impl<'a> core::fmt::Debug for Reader<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(
&::core::convert::Into::<crate::dynamic_value::Reader<'_>>::into(*self),
f,
)
}
}