Skip to main content

fory_core/serializer/
unknown_case.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::error::Error;
20use crate::resolver::{RefFlag, RefMode};
21use crate::serializer::any::check_erased_target_type;
22use crate::serializer::Serializer;
23use crate::type_id::{self, TypeId};
24use crate::types::UnknownCase;
25use std::any::Any;
26use std::sync::Arc;
27
28#[doc(hidden)]
29pub fn write_unknown_case_body(
30    context: &mut WriteContext,
31    unknown: &UnknownCase,
32) -> Result<(), Error> {
33    if write_typed_unknown_case_body(context, unknown)? {
34        return Ok(());
35    }
36    <Arc<dyn Any + Send + Sync> as Serializer>::write(
37        unknown.value_arc(),
38        context,
39        RefMode::Tracking,
40        true,
41    )
42}
43
44fn write_typed_unknown_case_body(
45    context: &mut WriteContext,
46    unknown: &UnknownCase,
47) -> Result<bool, Error> {
48    let type_id = unknown.type_id();
49    if type_id == type_id::UNKNOWN && unknown.downcast_ref::<()>().is_some() {
50        context.writer.write_i8(RefFlag::Null as i8);
51        return Ok(true);
52    }
53    if !has_typed_value(unknown) {
54        return Ok(false);
55    }
56    // UnknownCase carriers intentionally keep only a wire type id plus the
57    // polymorphic value. For internal numeric ids, the id byte is the complete
58    // Any type metadata. Scalar Any values are not ref-tracked, so their ref
59    // metadata is always NotNullValue before the original numeric encoding.
60    // Other types fall back to the normal Arc<dyn Any + Send + Sync> path.
61    context.writer.write_i8(RefFlag::NotNullValue as i8);
62    context.writer.write_u8(type_id as u8);
63    match type_id {
64        type_id::BOOL => context
65            .writer
66            .write_bool(*unknown.downcast_ref::<bool>().unwrap()),
67        type_id::INT8 => context
68            .writer
69            .write_i8(*unknown.downcast_ref::<i8>().unwrap()),
70        type_id::INT16 => context
71            .writer
72            .write_i16(*unknown.downcast_ref::<i16>().unwrap()),
73        type_id::INT32 => context
74            .writer
75            .write_i32(*unknown.downcast_ref::<i32>().unwrap()),
76        type_id::VARINT32 => context
77            .writer
78            .write_var_i32(*unknown.downcast_ref::<i32>().unwrap()),
79        type_id::INT64 => context
80            .writer
81            .write_i64(*unknown.downcast_ref::<i64>().unwrap()),
82        type_id::VARINT64 => context
83            .writer
84            .write_var_i64(*unknown.downcast_ref::<i64>().unwrap()),
85        type_id::TAGGED_INT64 => context
86            .writer
87            .write_tagged_i64(*unknown.downcast_ref::<i64>().unwrap()),
88        type_id::UINT8 => context
89            .writer
90            .write_u8(*unknown.downcast_ref::<u8>().unwrap()),
91        type_id::UINT16 => context
92            .writer
93            .write_u16(*unknown.downcast_ref::<u16>().unwrap()),
94        type_id::UINT32 => context
95            .writer
96            .write_u32(*unknown.downcast_ref::<u32>().unwrap()),
97        type_id::VAR_UINT32 => context
98            .writer
99            .write_var_u32(*unknown.downcast_ref::<u32>().unwrap()),
100        type_id::UINT64 => context
101            .writer
102            .write_u64(*unknown.downcast_ref::<u64>().unwrap()),
103        type_id::VAR_UINT64 => context
104            .writer
105            .write_var_u64(*unknown.downcast_ref::<u64>().unwrap()),
106        type_id::TAGGED_UINT64 => context
107            .writer
108            .write_tagged_u64(*unknown.downcast_ref::<u64>().unwrap()),
109        _ => return Ok(false),
110    }
111    Ok(true)
112}
113
114fn has_typed_value(unknown: &UnknownCase) -> bool {
115    match unknown.type_id() {
116        type_id::BOOL => unknown.downcast_ref::<bool>().is_some(),
117        type_id::INT8 => unknown.downcast_ref::<i8>().is_some(),
118        type_id::INT16 => unknown.downcast_ref::<i16>().is_some(),
119        type_id::INT32 | type_id::VARINT32 => unknown.downcast_ref::<i32>().is_some(),
120        type_id::INT64 | type_id::VARINT64 | type_id::TAGGED_INT64 => {
121            unknown.downcast_ref::<i64>().is_some()
122        }
123        type_id::UINT8 => unknown.downcast_ref::<u8>().is_some(),
124        type_id::UINT16 => unknown.downcast_ref::<u16>().is_some(),
125        type_id::UINT32 | type_id::VAR_UINT32 => unknown.downcast_ref::<u32>().is_some(),
126        type_id::UINT64 | type_id::VAR_UINT64 | type_id::TAGGED_UINT64 => {
127            unknown.downcast_ref::<u64>().is_some()
128        }
129        _ => false,
130    }
131}
132
133#[doc(hidden)]
134pub fn read_unknown_case_body(
135    context: &mut ReadContext,
136    case_id: u32,
137) -> Result<UnknownCase, Error> {
138    let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
139    match ref_flag {
140        RefFlag::Null => Ok(UnknownCase::new(case_id, ())),
141        RefFlag::Ref => {
142            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
143            let value = context
144                .ref_reader
145                .get_arc_ref::<dyn std::any::Any + Send + Sync>(ref_id)
146                .ok_or_else(|| {
147                    Error::invalid_data(format!("UnknownCase ref {} not found", ref_id))
148                })?;
149            Ok(UnknownCase::from_runtime(
150                case_id,
151                TypeId::UNKNOWN as u32,
152                value,
153            ))
154        }
155        RefFlag::NotNullValue | RefFlag::RefValue => {
156            let ref_id = if matches!(ref_flag, RefFlag::RefValue) {
157                // The wire ref id belongs to the unknown value itself. Reserve it
158                // before reading nested fields so their own refs keep the
159                // same ids written by the normal reference engine.
160                Some(context.ref_reader.reserve_ref_id())
161            } else {
162                None
163            };
164            // The unknown-case serializer owns only the union body envelope. It must
165            // not add a depth frame here: the decoded Any value is not a new nesting
166            // boundary by itself, and real nested value serializers perform their
167            // own depth checks.
168            let type_info = context.read_any_type_info()?;
169            check_erased_target_type(&type_info)?;
170            let value = type_info.get_harness().read_arc_any(context, &type_info)?;
171            if let Some(ref_id) = ref_id {
172                context.ref_reader.store_arc_ref_at(ref_id, value.clone());
173            }
174            Ok(UnknownCase::from_runtime(
175                case_id,
176                type_info.get_type_id() as u32,
177                value,
178            ))
179        }
180    }
181}
182
183impl Serializer for UnknownCase {
184    type Target = Self;
185
186    fn write(
187        value: &Self,
188        context: &mut WriteContext,
189        ref_mode: RefMode,
190        write_type_info: bool,
191    ) -> Result<(), Error> {
192        let _ = ref_mode;
193        let _ = write_type_info;
194        write_unknown_case_body(context, value)
195    }
196
197    fn write_data(value: &Self, context: &mut WriteContext) -> Result<(), Error> {
198        write_unknown_case_body(context, value)
199    }
200
201    fn read(
202        context: &mut ReadContext,
203        ref_mode: RefMode,
204        read_type_info: bool,
205    ) -> Result<Self, Error> {
206        let _ = ref_mode;
207        let _ = read_type_info;
208        read_unknown_case_body(context, 0)
209    }
210
211    fn read_data(context: &mut ReadContext) -> Result<Self, Error> {
212        read_unknown_case_body(context, 0)
213    }
214
215    fn default_value(_: &mut ReadContext) -> Result<Self, Error> {
216        Ok(UnknownCase::new(0, ()))
217    }
218
219    fn read_arc_any(context: &mut ReadContext) -> Result<Arc<dyn Any + Send + Sync>, Error> {
220        Ok(Arc::new(read_unknown_case_body(context, 0)?))
221    }
222
223    fn static_type_id() -> TypeId {
224        TypeId::UNKNOWN
225    }
226}