Skip to main content

fory_core/serializer/
enum_.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::context::{ReadContext, WriteContext};
19use crate::ensure;
20use crate::error::Error;
21use crate::meta::FieldInfo;
22use crate::resolver::{RefFlag, RefMode, TypeResolver};
23use crate::serializer::{ForyDefault, Serializer};
24use crate::type_id::TypeId;
25
26#[inline(always)]
27pub fn actual_type_id(_type_id: u32, register_by_name: bool, _compatible: bool) -> u32 {
28    if register_by_name {
29        TypeId::NAMED_ENUM as u32
30    } else {
31        TypeId::ENUM as u32
32    }
33}
34
35#[inline(always)]
36pub fn write<T: Serializer>(
37    this: &T,
38    context: &mut WriteContext,
39    ref_mode: RefMode,
40    write_type_info: bool,
41) -> Result<(), Error> {
42    if ref_mode != RefMode::None {
43        context.writer.write_i8(RefFlag::NotNullValue as i8);
44    }
45    if write_type_info {
46        T::fory_write_type_info(context)?;
47    }
48    this.fory_write_data(context)
49}
50
51#[inline(always)]
52pub fn write_type_info<T: Serializer>(context: &mut WriteContext) -> Result<(), Error> {
53    let type_id = T::fory_get_type_id(context.get_type_resolver())?;
54    context.writer.write_u8(type_id as u8);
55    let rs_type_id = std::any::TypeId::of::<T>();
56    if type_id == TypeId::ENUM {
57        let type_info = context.get_type_resolver().get_type_info(&rs_type_id)?;
58        context.writer.write_var_u32(type_info.get_user_type_id());
59        return Ok(());
60    }
61    if context.is_share_meta() {
62        // Write type meta inline using streaming protocol
63        context.write_type_meta(rs_type_id)?;
64    } else {
65        let type_info = context.get_type_resolver().get_type_info(&rs_type_id)?;
66        let namespace = type_info.get_namespace();
67        let type_name = type_info.get_type_name();
68        context.write_meta_string_bytes(namespace)?;
69        context.write_meta_string_bytes(type_name)?;
70    }
71    Ok(())
72}
73
74#[inline(always)]
75pub fn read<T: Serializer + ForyDefault>(
76    context: &mut ReadContext,
77    ref_mode: RefMode,
78    read_type_info: bool,
79) -> Result<T, Error> {
80    let ref_flag = if ref_mode != RefMode::None {
81        context.reader.read_i8()?
82    } else {
83        RefFlag::NotNullValue as i8
84    };
85    if ref_flag == RefFlag::Null as i8 {
86        Ok(T::fory_default())
87    } else if ref_flag == (RefFlag::NotNullValue as i8) || ref_flag == (RefFlag::RefValue as i8) {
88        if read_type_info {
89            T::fory_read_type_info(context)?;
90        }
91        T::fory_read_data(context)
92    } else if ref_flag == (RefFlag::Ref as i8) {
93        Err(Error::invalid_ref("Invalid ref, enum type is not a ref"))
94    } else {
95        Err(Error::invalid_data(format!(
96            "Unknown ref flag: {}",
97            ref_flag
98        )))
99    }
100}
101
102#[inline(always)]
103pub fn read_type_info<T: Serializer>(context: &mut ReadContext) -> Result<(), Error> {
104    let local_type_id = T::fory_get_type_id(context.get_type_resolver())?;
105    let remote_type_id = context.reader.read_u8()?;
106    ensure!(
107        local_type_id as u8 == remote_type_id,
108        Error::type_mismatch(local_type_id as u32, remote_type_id as u32)
109    );
110    if remote_type_id == TypeId::NAMED_ENUM as u8 {
111        if context.is_share_meta() {
112            // Read type meta inline using streaming protocol
113            let _type_info = context.read_type_meta()?;
114        } else {
115            let _namespace_msb = context.read_meta_string()?;
116            let _type_name_msb = context.read_meta_string()?;
117        }
118    } else {
119        context.reader.read_var_u32()?;
120    }
121    Ok(())
122}
123
124pub trait NamedEnumVariantMetaTrait: 'static {
125    fn fory_get_sorted_field_names() -> &'static [&'static str] {
126        &[]
127    }
128
129    #[allow(unused_variables)]
130    fn fory_fields_info(type_resolver: &TypeResolver) -> Result<Vec<FieldInfo>, Error> {
131        Ok(Vec::default())
132    }
133}