use crate::constants;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct SerializationStream {
pub version: u16,
pub contents: Vec<ContentElement>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum ContentElement {
Object(StreamObject),
BlockData(BlockData),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum StreamObject {
NewObject(NewObject),
NewClass(NewClass),
NewArray(NewArray),
NewString(StreamString),
NewEnum(NewEnum),
NewClassDesc(ClassDesc),
PrevObject { handle: u32 },
NullReference,
Exception,
Reset,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct NewObject {
pub class_desc: ClassDescRef,
pub handle: u32,
pub class_data: Vec<ClassData>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct NewClass {
pub class_desc: ClassDescRef,
pub handle: u32,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct NewArray {
pub class_desc: ClassDescRef,
pub handle: u32,
pub size: u32,
pub values: ArrayValues,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum ArrayValues {
Byte(Vec<i8>),
Char(Vec<u16>),
Double(Vec<f64>),
Float(Vec<f32>),
Int(Vec<i32>),
Long(Vec<i64>),
Short(Vec<i16>),
Boolean(Vec<u8>),
Object(Vec<Option<StreamObject>>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct StreamString {
pub value: String,
pub handle: u32,
pub is_long: bool,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct NewEnum {
pub class_desc: ClassDescRef,
pub handle: u32,
pub constant_name: StreamString,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum ClassDescRef {
Inline(Box<ClassDesc>),
Null,
Reference { handle: u32 },
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum ClassDesc {
Normal(Box<NormalClassDesc>),
Proxy(ProxyClassDesc),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct NormalClassDesc {
pub class_name: String,
pub serial_version_uid: i64,
pub handle: u32,
pub flags: u8,
pub fields: Vec<FieldDesc>,
pub class_annotation: Vec<AnnotationElement>,
pub super_class_desc: Box<ClassDescRef>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct ProxyClassDesc {
pub handle: u32,
pub interface_names: Vec<String>,
pub class_annotation: Vec<AnnotationElement>,
pub super_class_desc: Box<ClassDescRef>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum FieldDesc {
Primitive(PrimitiveFieldDesc),
Object(ObjectFieldDesc),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct PrimitiveFieldDesc {
pub type_code: u8,
pub field_name: String,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct ObjectFieldDesc {
pub type_code: u8,
pub field_name: String,
pub class_name: String,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum AnnotationElement {
Object(StreamObject),
BlockData(BlockData),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum BlockData {
Short { data: Vec<u8> },
Long { data: Vec<u8> },
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum ClassData {
NoWriteMethod(FieldValueSet),
WriteMethodWithFields(FieldValueSet, ObjectAnnotation),
WriteMethod(ObjectAnnotation),
ExternalContents(Vec<u8>),
ExternalBlockData(ObjectAnnotation),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct FieldValueSet {
pub values: Vec<FieldValue>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub enum FieldValue {
Byte(i8),
Char(u16),
Double(f64),
Float(f32),
Int(i32),
Long(i64),
Short(i16),
Boolean(bool),
Object(Option<Box<StreamObject>>),
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct ObjectAnnotation {
pub contents: Vec<AnnotationElement>,
}
impl NormalClassDesc {
pub fn has_write_method(&self) -> bool {
self.flags & constants::SC_WRITE_METHOD != 0
}
pub fn is_serializable(&self) -> bool {
self.flags & constants::SC_SERIALIZABLE != 0
}
pub fn is_externalizable(&self) -> bool {
self.flags & constants::SC_EXTERNALIZABLE != 0
}
pub fn has_block_data(&self) -> bool {
self.flags & constants::SC_BLOCK_DATA != 0
}
pub fn is_enum(&self) -> bool {
self.flags & constants::SC_ENUM != 0
}
}
impl BlockData {
pub fn data(&self) -> &[u8] {
match self {
BlockData::Short { data } => data,
BlockData::Long { data } => data,
}
}
}
impl ClassDescRef {
pub fn class_name(&self) -> Option<&str> {
match self {
ClassDescRef::Inline(cd) => cd.class_name(),
ClassDescRef::Null => None,
ClassDescRef::Reference { .. } => None,
}
}
}
impl ClassDesc {
pub fn class_name(&self) -> Option<&str> {
match self {
ClassDesc::Normal(desc) => Some(&desc.class_name),
ClassDesc::Proxy(_) => None,
}
}
}
impl NewObject {
pub fn class_name(&self) -> Option<&str> {
self.class_desc.class_name()
}
}
impl NewArray {
pub fn class_name(&self) -> Option<&str> {
self.class_desc.class_name()
}
}
impl StreamObject {
pub fn handle(&self) -> Option<u32> {
match self {
StreamObject::NewObject(o) => Some(o.handle),
StreamObject::NewClass(c) => Some(c.handle),
StreamObject::NewArray(a) => Some(a.handle),
StreamObject::NewString(s) => Some(s.handle),
StreamObject::NewEnum(e) => Some(e.handle),
StreamObject::NewClassDesc(ClassDesc::Normal(d)) => Some(d.handle),
StreamObject::NewClassDesc(ClassDesc::Proxy(d)) => Some(d.handle),
StreamObject::PrevObject { handle } => Some(*handle),
StreamObject::NullReference | StreamObject::Exception | StreamObject::Reset => None,
}
}
}
impl SerializationStream {
pub fn objects(&self) -> impl Iterator<Item = &StreamObject> {
self.contents.iter().filter_map(|c| match c {
ContentElement::Object(obj) => Some(obj),
ContentElement::BlockData(_) => None,
})
}
}