protobuf_core/
field.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Field-level I/O utilities for Protocol Buffers
16//!
17//! This module provides primitive utilities for reading and writing raw protobuf fields.
18//! These are building blocks for constructing higher-level parsers and serializers,
19//! not a complete message parser or serializer.
20//!
21//! ## Core Types
22//!
23//! The `Field` and `FieldValue` types are always available when this module is enabled.
24//!
25//! ## Reading (Deserialization)
26//!
27//! Available when the `read` feature is enabled.
28//!
29//! The utilities read fields sequentially from input sources that implement `std::io::Read`,
30//! returning raw field values (varint bytes, fixed-width bytes, or length-delimited bytes)
31//! without interpretation of the semantic meaning.
32//!
33//! ## Writing (Serialization)
34//!
35//! Available when the `write` feature is enabled.
36//!
37//! The utilities write fields to output targets that implement `std::io::Write`,
38//! encoding field numbers, wire types, and values into the protobuf wire format.
39
40use crate::field_number::FieldNumber;
41use crate::tag::Tag;
42use crate::varint::Varint;
43use crate::wire_format::WireType;
44
45#[cfg(feature = "read")]
46pub mod read;
47
48#[cfg(feature = "write")]
49pub mod write;
50
51// Re-export read functionality
52#[cfg(feature = "read")]
53pub use self::read::{ProtobufFieldIterator, ReadExtProtobuf};
54
55// Re-export write functionality
56#[cfg(feature = "write")]
57pub use self::write::WriteExtProtobuf;
58
59/// A raw field value read from the wire
60///
61/// This represents the raw bytes of a field value without semantic interpretation.
62/// The caller is responsible for converting these raw values to the appropriate types
63/// based on the field's schema definition.
64#[derive(Debug, Clone, PartialEq)]
65pub enum FieldValue {
66    /// Variable-width integers (Int32, Int64, UInt32, UInt64, SInt32, SInt64, Bool, Enum)
67    Varint(Varint),
68    /// 32-bit fixed-width values (Fixed32, SFixed32, Float)
69    I32([u8; 4]),
70    /// 64-bit fixed-width values (Fixed64, SFixed64, Double)
71    I64([u8; 8]),
72    /// Length-delimited values (String, Bytes, embedded messages, packed repeated fields)
73    Len(Vec<u8>),
74}
75
76impl FieldValue {
77    // Varint constructors
78
79    /// Create a field value from a Varint
80    pub fn from_varint(varint: Varint) -> Self {
81        Self::Varint(varint)
82    }
83
84    /// Create a field value from a UInt64 protobuf type
85    pub fn from_uint64(value: u64) -> Self {
86        Self::Varint(Varint::from_uint64(value))
87    }
88
89    /// Create a field value from a UInt32 protobuf type
90    pub fn from_uint32(value: u32) -> Self {
91        Self::Varint(Varint::from_uint32(value))
92    }
93
94    /// Create a field value from a SInt64 protobuf type (ZigZag encoded)
95    pub fn from_sint64(value: i64) -> Self {
96        Self::Varint(Varint::from_sint64(value))
97    }
98
99    /// Create a field value from a SInt32 protobuf type (ZigZag encoded)
100    pub fn from_sint32(value: i32) -> Self {
101        Self::Varint(Varint::from_sint32(value))
102    }
103
104    /// Create a field value from an Int64 protobuf type (non-ZigZag)
105    pub fn from_int64(value: i64) -> Self {
106        Self::Varint(Varint::from_int64(value))
107    }
108
109    /// Create a field value from an Int32 protobuf type (non-ZigZag)
110    pub fn from_int32(value: i32) -> Self {
111        Self::Varint(Varint::from_int32(value))
112    }
113
114    /// Create a field value from a Bool protobuf type
115    pub fn from_bool(value: bool) -> Self {
116        Self::Varint(Varint::from_bool(value))
117    }
118
119    // Fixed-width constructors
120
121    /// Create a field value from a Fixed32 protobuf type
122    pub fn from_fixed32(value: u32) -> Self {
123        Self::I32(value.to_le_bytes())
124    }
125
126    /// Create a field value from a SFixed32 protobuf type
127    pub fn from_sfixed32(value: i32) -> Self {
128        Self::I32(value.to_le_bytes())
129    }
130
131    /// Create a field value from a Float protobuf type
132    pub fn from_float(value: f32) -> Self {
133        Self::I32(value.to_le_bytes())
134    }
135
136    /// Create a field value from a Fixed64 protobuf type
137    pub fn from_fixed64(value: u64) -> Self {
138        Self::I64(value.to_le_bytes())
139    }
140
141    /// Create a field value from a SFixed64 protobuf type
142    pub fn from_sfixed64(value: i64) -> Self {
143        Self::I64(value.to_le_bytes())
144    }
145
146    /// Create a field value from a Double protobuf type
147    pub fn from_double(value: f64) -> Self {
148        Self::I64(value.to_le_bytes())
149    }
150
151    // Length-delimited constructors
152
153    /// Create a field value from raw bytes (Bytes protobuf type)
154    pub fn from_bytes(data: Vec<u8>) -> Self {
155        Self::Len(data)
156    }
157
158    /// Create a field value from a String protobuf type
159    pub fn from_string(s: String) -> Self {
160        Self::Len(s.into_bytes())
161    }
162
163    /// Calculate the encoded size of this field value in bytes (excluding the tag)
164    ///
165    /// For Len values, this includes the length varint plus the data bytes.
166    pub fn encoded_size(&self) -> usize {
167        match self {
168            Self::Varint(varint) => varint.varint_size(),
169            Self::I32(_) => 4,
170            Self::I64(_) => 8,
171            Self::Len(data) => {
172                let length = data.len() as u64;
173                let length_varint = Varint::from_uint64(length);
174                length_varint.varint_size() + data.len()
175            }
176        }
177    }
178}
179
180/// A raw field read from the wire
181///
182/// Contains the field number and the raw field value.
183/// The caller must interpret the value based on the message schema.
184#[derive(Debug, Clone, PartialEq)]
185pub struct Field {
186    pub field_number: FieldNumber,
187    pub value: FieldValue,
188}
189
190impl Field {
191    /// Create a new field with the given field number and value
192    pub fn new(field_number: FieldNumber, value: FieldValue) -> Self {
193        Self {
194            field_number,
195            value,
196        }
197    }
198
199    /// Calculate the total encoded size of this field in bytes (tag + value)
200    pub fn encoded_size(&self) -> usize {
201        // Tag size (field number shifted left by 3 bits to make room for wire type)
202        let wire_type = match &self.value {
203            FieldValue::Varint(_) => WireType::Varint,
204            FieldValue::I32(_) => WireType::Int32,
205            FieldValue::I64(_) => WireType::Int64,
206            FieldValue::Len(_) => WireType::Len,
207        };
208        let tag = Tag {
209            field_number: self.field_number,
210            wire_type,
211        };
212        let tag_varint = tag.to_encoded();
213        let tag_size = tag_varint.varint_size();
214
215        // Value size
216        let value_size = self.value.encoded_size();
217
218        tag_size + value_size
219    }
220}