#[cfg(test)]
mod test_every_field_set;
use std::fmt;
use chrono_tz::Tz;
use crate::{
generate, guess,
json::{self},
price, schema, tariff,
warning::{Caveat, IntoCaveat as _},
Verdict,
};
pub fn infer_version(json: json::Document<'_>) -> guess::CdrVersion<'_> {
guess::cdr_version(json)
}
pub fn build(
json: json::Document<'_>,
version: crate::Version,
) -> Caveat<Versioned<'_>, schema::Warning> {
let (version, warnings) = match version {
crate::Version::V221 => {
let (cdr, warnings) = schema::v221::build_cdr(&json).into_parts();
(Version::V221(cdr), warnings)
}
crate::Version::V211 => {
let (cdr, warnings) = schema::v211::build_cdr(&json).into_parts();
(Version::V211(cdr), warnings)
}
};
let versioned = Versioned { doc: json, version };
versioned.into_caveat(warnings)
}
pub fn build_versioned(json: VersionedJson<'_>) -> Caveat<Versioned<'_>, schema::Warning> {
let VersionedJson { doc, version } = json;
build(doc, version)
}
pub fn generate_from_tariff(
tariff: &tariff::Versioned<'_>,
config: &generate::Config,
) -> Verdict<generate::Report, generate::Warning> {
generate::cdr_from_tariff(tariff, config)
}
pub fn price(
cdr: &Versioned<'_>,
tariff_source: price::TariffSource<'_>,
timezone: Tz,
) -> Verdict<price::Report, price::Warning> {
price::cdr(cdr, tariff_source, timezone)
}
#[derive(Clone)]
pub struct Versioned<'buf> {
doc: json::Document<'buf>,
version: Version<'buf>,
}
impl fmt::Debug for Versioned<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
match &self.version {
Version::V211(cdr) => fmt::Debug::fmt(&cdr, f),
Version::V221(cdr) => fmt::Debug::fmt(&cdr, f),
}
} else {
match &self.version {
Version::V211(_) => f.write_str("V211"),
Version::V221(_) => f.write_str("V221"),
}
}
}
}
impl crate::Versioned for Versioned<'_> {
fn version(&self) -> crate::Version {
match self.version {
Version::V211(_) => crate::Version::V211,
Version::V221(_) => crate::Version::V221,
}
}
}
impl<'buf> Versioned<'buf> {
pub fn into_doc(self) -> json::Document<'buf> {
self.doc
}
pub fn as_element(&self) -> &json::Element<'buf> {
self.doc.root()
}
pub fn as_doc(&self) -> &json::Document<'buf> {
&self.doc
}
pub fn as_json_str(&self) -> &'buf str {
self.doc.source()
}
}
#[expect(
clippy::large_enum_variant,
reason = "the v2.1.1 and v2.2.1 CDR IRs differ in size; this short-lived versioned \
value is not worth boxing"
)]
#[derive(Clone)]
enum Version<'buf> {
V211(schema::v211::Cdr<'buf>),
V221(schema::v221::Cdr<'buf>),
}
pub struct VersionedJson<'buf> {
doc: json::Document<'buf>,
version: crate::Version,
}
impl fmt::Debug for VersionedJson<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
fmt::Debug::fmt(&self.doc, f)
} else {
match self.version {
crate::Version::V211 => f.write_str("V211"),
crate::Version::V221 => f.write_str("V221"),
}
}
}
}
impl crate::Versioned for VersionedJson<'_> {
fn version(&self) -> crate::Version {
self.version
}
}
impl<'buf> VersionedJson<'buf> {
pub(crate) fn new(element: json::Document<'buf>, version: crate::Version) -> Self {
Self {
doc: element,
version,
}
}
pub fn into_doc(self) -> json::Document<'buf> {
self.doc
}
pub fn as_element(&self) -> &json::Element<'buf> {
self.doc.root()
}
pub fn as_doc(&self) -> &json::Document<'buf> {
&self.doc
}
pub fn as_json_str(&self) -> &'buf str {
self.doc.source()
}
}
#[derive(Debug)]
pub struct Unversioned<'buf> {
doc: json::Document<'buf>,
}
impl<'buf> Unversioned<'buf> {
pub(crate) fn new(doc: json::Document<'buf>) -> Self {
Self { doc }
}
pub fn into_doc(self) -> json::Document<'buf> {
self.doc
}
pub fn as_element(&self) -> &json::Element<'buf> {
self.doc.root()
}
}
impl<'buf> crate::Unversioned for Unversioned<'buf> {
type Versioned = VersionedJson<'buf>;
fn force_into_versioned(self, version: crate::Version) -> VersionedJson<'buf> {
let Self { doc } = self;
VersionedJson { doc, version }
}
}