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