1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use std::convert::TryFrom;
use crate::result::{decoding_error, IonError};
use crate::types::IonType;
/// Represents the type information found in the header byte of each binary Ion value.
/// While this value can be readily mapped to a user-level [`IonType`], it is a distinct concept.
/// The IonTypeCode enum captures system-level information that is not exposed to end users of the
/// library, including:
/// * Whether the cursor is positioned over whitespace that needs to be skipped.
/// * Whether the integer value being read is positive or negative.
/// * Whether the next type code is reserved.
///
/// See the
/// [Typed Value Formats](https://amazon-ion.github.io/ion-docs/docs/binary.html#typed-value-formats)
/// section of the spec for more information.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum IonTypeCode {
NullOrNop, // 0
Boolean, // 1
PositiveInteger, // 2
NegativeInteger, // 3
Float, // 4
Decimal, // 5
Timestamp, // 6
Symbol, // 7
String, // 8
Clob, // 9
Blob, // 10
List, // 11
SExpression, // 12
Struct, // 13
AnnotationOrIvm, // 14
Reserved, // 15
}
impl TryFrom<IonTypeCode> for IonType {
type Error = IonError;
/// Attempts to convert the system-level IonTypeCode into the corresponding user-level IonType.
fn try_from(ion_type_code: IonTypeCode) -> Result<Self, Self::Error> {
use IonTypeCode::*;
let ion_type = match ion_type_code {
NullOrNop => IonType::Null,
Boolean => IonType::Bool,
PositiveInteger | NegativeInteger => IonType::Int,
Float => IonType::Float,
Decimal => IonType::Decimal,
Timestamp => IonType::Timestamp,
Symbol => IonType::Symbol,
String => IonType::String,
Clob => IonType::Clob,
Blob => IonType::Blob,
List => IonType::List,
SExpression => IonType::SExp,
Struct => IonType::Struct,
_ => {
return decoding_error(format!(
"Attempted to make an IonType from an invalid type code: {ion_type_code:?}"
));
}
};
Ok(ion_type)
}
}
impl TryFrom<u8> for IonTypeCode {
type Error = IonError;
/// Attempts to convert the provided byte into an IonTypeCode. Any value greater than 15
/// will result in an Error.
fn try_from(type_code: u8) -> Result<Self, Self::Error> {
use IonTypeCode::*;
let ion_type_code = match type_code {
0 => NullOrNop,
1 => Boolean,
2 => PositiveInteger,
3 => NegativeInteger,
4 => Float,
5 => Decimal,
6 => Timestamp,
7 => Symbol,
8 => String,
9 => Clob,
10 => Blob,
11 => List,
12 => SExpression,
13 => Struct,
14 => AnnotationOrIvm,
15 => Reserved,
_ => {
return decoding_error(format!("{type_code:?} is not a valid header type code."));
}
};
Ok(ion_type_code)
}
}
impl IonTypeCode {
/// Constant function to convert an [`IonTypeCode`] into a `u8`.
pub const fn to_u8(self) -> u8 {
use IonTypeCode::*;
match self {
NullOrNop => 0,
Boolean => 1,
PositiveInteger => 2,
NegativeInteger => 3,
Float => 4,
Decimal => 5,
Timestamp => 6,
Symbol => 7,
String => 8,
Clob => 9,
Blob => 10,
List => 11,
SExpression => 12,
Struct => 13,
AnnotationOrIvm => 14,
Reserved => 15,
}
}
}