mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 03:07:13 +00:00
cuekit and cuenorm: three subtitle formats, one cue stream
This commit is contained in:
@@ -26,18 +26,12 @@ pub struct Chunk {
|
||||
/// What part of the work the passage belongs to.
|
||||
pub role: Role,
|
||||
/// Seconds from the start of the recording, for timed sources.
|
||||
#[serde(
|
||||
default,
|
||||
serialize_with = "crate::float::serialize_option",
|
||||
deserialize_with = "crate::float::deserialize_option"
|
||||
)]
|
||||
#[serde(default, with = "crate::finite::option")]
|
||||
#[schemars(with = "Option<f64>")]
|
||||
pub start_time: Option<f64>,
|
||||
/// Seconds from the start of the recording, for timed sources.
|
||||
#[serde(
|
||||
default,
|
||||
serialize_with = "crate::float::serialize_option",
|
||||
deserialize_with = "crate::float::deserialize_option"
|
||||
)]
|
||||
#[serde(default, with = "crate::finite::option")]
|
||||
#[schemars(with = "Option<f64>")]
|
||||
pub end_time: Option<f64>,
|
||||
/// Set tags; see [`flags`]. Sorted and deduplicated on the way in and on
|
||||
/// the way out, so the same set of flags is always the same bytes
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//! Serde plumbing for floats that JSON can actually carry.
|
||||
//!
|
||||
//! Use it as `#[serde(with = "corpus_core::finite")]` on an `f64`, or
|
||||
//! `#[serde(default, with = "corpus_core::finite::option")]` on an
|
||||
//! `Option<f64>`.
|
||||
//!
|
||||
//! JSON has no spelling for NaN or infinity, and `serde_json` writes them as
|
||||
//! `null`. That is a silent corruption in both directions: a score written as
|
||||
//! `null` fails to read back and kills the stream at the consumer, and a
|
||||
//! timestamp written as `null` reads back as "no timestamp" with nothing to
|
||||
//! say it was ever anything else. So a non-finite number is refused where it
|
||||
//! is produced, which is the only place anyone can still fix it.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serializer, de::Error as _, ser::Error as _};
|
||||
|
||||
/// Write a float, refusing one JSON cannot carry.
|
||||
pub fn serialize<S: Serializer>(value: &f64, out: S) -> Result<S::Ok, S::Error> {
|
||||
if !value.is_finite() {
|
||||
return Err(S::Error::custom(format!(
|
||||
"{value} cannot be written as JSON"
|
||||
)));
|
||||
}
|
||||
out.serialize_f64(*value)
|
||||
}
|
||||
|
||||
/// Read a float, refusing one that is not finite.
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(input: D) -> Result<f64, D::Error> {
|
||||
let value = f64::deserialize(input)?;
|
||||
if !value.is_finite() {
|
||||
return Err(D::Error::custom(format!("{value} is not a finite number")));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
/// The same, for a field that may be absent.
|
||||
pub mod option {
|
||||
use serde::{Deserialize, Deserializer, Serializer, de::Error as _};
|
||||
|
||||
/// Write an optional float, refusing one JSON cannot carry.
|
||||
pub fn serialize<S: Serializer>(value: &Option<f64>, out: S) -> Result<S::Ok, S::Error> {
|
||||
match value {
|
||||
Some(value) => super::serialize(value, out),
|
||||
None => out.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Read an optional float, refusing one that is not finite.
|
||||
pub fn deserialize<'de, D: Deserializer<'de>>(input: D) -> Result<Option<f64>, D::Error> {
|
||||
let value = Option::<f64>::deserialize(input)?;
|
||||
match value {
|
||||
Some(value) if !value.is_finite() => {
|
||||
Err(D::Error::custom(format!("{value} is not a finite number")))
|
||||
}
|
||||
value => Ok(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
//! Serde plumbing for floats that JSON can actually carry.
|
||||
//!
|
||||
//! JSON has no spelling for NaN or infinity, and `serde_json` writes them as
|
||||
//! `null`. That is a silent corruption in both directions: a score written as
|
||||
//! `null` fails to read back and kills the stream at the consumer, and a
|
||||
//! timestamp written as `null` reads back as "no timestamp" with nothing to
|
||||
//! say it was ever anything else. So a non-finite number is refused where it
|
||||
//! is produced, which is the only place anyone can still fix it.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serializer, de::Error as _, ser::Error as _};
|
||||
|
||||
pub(crate) fn serialize<S: Serializer>(value: &f64, out: S) -> Result<S::Ok, S::Error> {
|
||||
if !value.is_finite() {
|
||||
return Err(S::Error::custom(format!(
|
||||
"{value} cannot be written as JSON"
|
||||
)));
|
||||
}
|
||||
out.serialize_f64(*value)
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_option<S: Serializer>(
|
||||
value: &Option<f64>,
|
||||
out: S,
|
||||
) -> Result<S::Ok, S::Error> {
|
||||
match value {
|
||||
Some(value) => serialize(value, out),
|
||||
None => out.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize<'de, D: Deserializer<'de>>(input: D) -> Result<f64, D::Error> {
|
||||
let value = f64::deserialize(input)?;
|
||||
if !value.is_finite() {
|
||||
return Err(D::Error::custom(format!("{value} is not a finite number")));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize_option<'de, D: Deserializer<'de>>(
|
||||
input: D,
|
||||
) -> Result<Option<f64>, D::Error> {
|
||||
let value = Option::<f64>::deserialize(input)?;
|
||||
match value {
|
||||
Some(value) if !value.is_finite() => {
|
||||
Err(D::Error::custom(format!("{value} is not a finite number")))
|
||||
}
|
||||
value => Ok(value),
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,8 @@ pub struct Hit {
|
||||
/// Position within the channel's own ranking, from one.
|
||||
pub rank: u32,
|
||||
/// The channel's raw score, on whatever scale that channel uses.
|
||||
#[serde(
|
||||
serialize_with = "crate::float::serialize",
|
||||
deserialize_with = "crate::float::deserialize"
|
||||
)]
|
||||
#[serde(with = "crate::finite")]
|
||||
#[schemars(with = "f64")]
|
||||
pub score: f64,
|
||||
/// Anything the producer wants to carry through fusion untouched.
|
||||
///
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
pub mod chunk;
|
||||
pub mod doc;
|
||||
pub mod exit;
|
||||
mod float;
|
||||
pub mod finite;
|
||||
pub mod hit;
|
||||
pub mod ndjson;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user