// @generated by jacquard-lexicon. DO NOT EDIT.
//
// Lexicon: net.anisota.lab.synth
//
// This file was automatically generated from Lexicon schemas.
// Any manual changes will be overwritten on the next regeneration.
#[allow(unused_imports)]
use alloc::collections::BTreeMap;
#[allow(unused_imports)]
use core::marker::PhantomData;
use jacquard_common::{BosStr, CowStr, DefaultStr, FromStaticStr};
#[allow(unused_imports)]
use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
use jacquard_common::deps::smol_str::SmolStr;
use jacquard_common::types::collection::{Collection, RecordError};
use jacquard_common::types::string::{AtUri, Cid, Datetime};
use jacquard_common::types::uri::{RecordUri, UriError};
use jacquard_common::types::value::Data;
use jacquard_common::xrpc::XrpcResp;
use jacquard_derive::{IntoStatic, lexicon};
use jacquard_lexicon::lexicon::LexiconDoc;
use jacquard_lexicon::schema::LexiconSchema;
#[allow(unused_imports)]
use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
use serde::{Deserialize, Serialize};
/// A multitrack composition made in the Anisota Lab's Synth studio and saved to the owner's library. The piece is stored as compact musical event data (not audio), so it can be reloaded into the synth, replayed and edited. The shared loop has a tempo and step length; each track is either a 'tone' voice (a waveform playing degrees of the composition's scale) or a 'drum' lane (the studio's synthesized kit). A track's notes are stored in 'cells' as interleaved integers — for a tone track [step, degree, step, degree, ...] where degree indexes the scale ladder; for a drum track [step, piece, ...] where piece is 0..4 (kick, snare, hat, clap, tom). 'fx' captures the rack the piece was shaped with.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
#[serde(
rename_all = "camelCase",
rename = "net.anisota.lab.synth",
tag = "$type",
bound(deserialize = "S: Deserialize<'de> + BosStr")
)]
pub struct Synth<S: BosStr = DefaultStr> {
///When the composition was saved
pub created_at: Datetime,
///The shared rack the composition was shaped with, each 0..100
#[serde(skip_serializing_if = "Option::is_none")]
pub fx: Option<SynthFx<S>>,
///Display name for the composition
pub name: S,
///Root note of the scale as a MIDI note number
#[serde(skip_serializing_if = "Option::is_none")]
pub root: Option<i64>,
///Scale the tone tracks' degrees are drawn from
#[serde(skip_serializing_if = "Option::is_none")]
pub scale: Option<S>,
///Number of sixteenth-note steps in the loop
pub steps: i64,
///Loop tempo in beats per minute
pub tempo: i64,
///The overlapping tracks, played together on the loop
pub tracks: Vec<Data<S>>,
#[serde(flatten, default, skip_serializing_if = "Option::is_none")]
pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
}
/// The shared rack the composition was shaped with, each 0..100
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic, Default)]
#[serde(
rename_all = "camelCase",
bound(deserialize = "S: Deserialize<'de> + BosStr")
)]
pub struct SynthFx<S: BosStr = DefaultStr> {
#[serde(skip_serializing_if = "Option::is_none")]
pub cutoff: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub drive: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub echo: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub master: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reso: Option<i64>,
#[serde(flatten, default, skip_serializing_if = "Option::is_none")]
pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
}
/// Typed wrapper for GetRecord response with this collection's record type.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
#[serde(rename_all = "camelCase")]
pub struct SynthGetRecordOutput<S: BosStr = DefaultStr> {
#[serde(skip_serializing_if = "Option::is_none")]
pub cid: Option<Cid<S>>,
pub uri: AtUri<S>,
pub value: Synth<S>,
}
impl<S: BosStr> Synth<S> {
pub fn uri(uri: S) -> Result<RecordUri<S, SynthRecord>, UriError> {
RecordUri::try_from_uri(AtUri::new(uri)?)
}
}
/// Marker type for deserializing records from this collection.
#[derive(Debug, Serialize, Deserialize)]
pub struct SynthRecord;
impl XrpcResp for SynthRecord {
const NSID: &'static str = "net.anisota.lab.synth";
const ENCODING: &'static str = "application/json";
type Output<S: BosStr> = SynthGetRecordOutput<S>;
type Err = RecordError;
}
impl<S: BosStr> From<SynthGetRecordOutput<S>> for Synth<S> {
fn from(output: SynthGetRecordOutput<S>) -> Self {
output.value
}
}
impl<S: BosStr> Collection for Synth<S> {
const NSID: &'static str = "net.anisota.lab.synth";
type Record = SynthRecord;
}
impl Collection for SynthRecord {
const NSID: &'static str = "net.anisota.lab.synth";
type Record = SynthRecord;
}
impl<S: BosStr> LexiconSchema for Synth<S> {
fn nsid() -> &'static str {
"net.anisota.lab.synth"
}
fn def_name() -> &'static str {
"main"
}
fn lexicon_doc() -> LexiconDoc<'static> {
lexicon_doc_net_anisota_lab_synth()
}
fn validate(&self) -> Result<(), ConstraintError> {
{
let value = &self.name;
#[allow(unused_comparisons)]
if <str>::len(value.as_ref()) > 800usize {
return Err(ConstraintError::MaxLength {
path: ValidationPath::from_field("name"),
max: 800usize,
actual: <str>::len(value.as_ref()),
});
}
}
{
let value = &self.name;
{
let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
if count > 100usize {
return Err(ConstraintError::MaxGraphemes {
path: ValidationPath::from_field("name"),
max: 100usize,
actual: count,
});
}
}
}
if let Some(ref value) = self.root {
if *value > 127i64 {
return Err(ConstraintError::Maximum {
path: ValidationPath::from_field("root"),
max: 127i64,
actual: *value,
});
}
}
if let Some(ref value) = self.root {
if *value < 0i64 {
return Err(ConstraintError::Minimum {
path: ValidationPath::from_field("root"),
min: 0i64,
actual: *value,
});
}
}
{
let value = &self.steps;
if *value > 64i64 {
return Err(ConstraintError::Maximum {
path: ValidationPath::from_field("steps"),
max: 64i64,
actual: *value,
});
}
}
{
let value = &self.steps;
if *value < 4i64 {
return Err(ConstraintError::Minimum {
path: ValidationPath::from_field("steps"),
min: 4i64,
actual: *value,
});
}
}
{
let value = &self.tempo;
if *value > 240i64 {
return Err(ConstraintError::Maximum {
path: ValidationPath::from_field("tempo"),
max: 240i64,
actual: *value,
});
}
}
{
let value = &self.tempo;
if *value < 40i64 {
return Err(ConstraintError::Minimum {
path: ValidationPath::from_field("tempo"),
min: 40i64,
actual: *value,
});
}
}
{
let value = &self.tracks;
#[allow(unused_comparisons)]
if value.len() > 32usize {
return Err(ConstraintError::MaxLength {
path: ValidationPath::from_field("tracks"),
max: 32usize,
actual: value.len(),
});
}
}
Ok(())
}
}
impl<S: BosStr> LexiconSchema for SynthFx<S> {
fn nsid() -> &'static str {
"net.anisota.lab.synth"
}
fn def_name() -> &'static str {
"SynthFx"
}
fn lexicon_doc() -> LexiconDoc<'static> {
lexicon_doc_net_anisota_lab_synth()
}
fn validate(&self) -> Result<(), ConstraintError> {
Ok(())
}
}
fn lexicon_doc_net_anisota_lab_synth() -> LexiconDoc<'static> {
use alloc::collections::BTreeMap;
#[allow(unused_imports)]
use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
use jacquard_lexicon::lexicon::*;
LexiconDoc {
lexicon: Lexicon::Lexicon1,
id: CowStr::new_static("net.anisota.lab.synth"),
defs: {
let mut map = BTreeMap::new();
map.insert(
SmolStr::new_static("main"),
LexUserType::Record(LexRecord {
description: Some(
CowStr::new_static(
"A multitrack composition made in the Anisota Lab's Synth studio and saved to the owner's library. The piece is stored as compact musical event data (not audio), so it can be reloaded into the synth, replayed and edited. The shared loop has a tempo and step length; each track is either a 'tone' voice (a waveform playing degrees of the composition's scale) or a 'drum' lane (the studio's synthesized kit). A track's notes are stored in 'cells' as interleaved integers — for a tone track [step, degree, step, degree, ...] where degree indexes the scale ladder; for a drum track [step, piece, ...] where piece is 0..4 (kick, snare, hat, clap, tom). 'fx' captures the rack the piece was shaped with.",
),
),
key: Some(CowStr::new_static("any")),
record: LexRecordRecord::Object(LexObject {
required: Some(
vec![
SmolStr::new_static("name"), SmolStr::new_static("tempo"),
SmolStr::new_static("steps"), SmolStr::new_static("tracks"),
SmolStr::new_static("createdAt")
],
),
properties: {
#[allow(unused_mut)]
let mut map = BTreeMap::new();
map.insert(
SmolStr::new_static("createdAt"),
LexObjectProperty::String(LexString {
description: Some(
CowStr::new_static("When the composition was saved"),
),
format: Some(LexStringFormat::Datetime),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("fx"),
LexObjectProperty::Object(LexObject {
description: Some(
CowStr::new_static(
"The shared rack the composition was shaped with, each 0..100",
),
),
properties: {
#[allow(unused_mut)]
let mut map = BTreeMap::new();
map.insert(
SmolStr::new_static("cutoff"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("drive"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("echo"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("master"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("reso"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map
},
..Default::default()
}),
);
map.insert(
SmolStr::new_static("name"),
LexObjectProperty::String(LexString {
description: Some(
CowStr::new_static("Display name for the composition"),
),
max_length: Some(800usize),
max_graphemes: Some(100usize),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("root"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(127i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("scale"),
LexObjectProperty::String(LexString {
description: Some(
CowStr::new_static(
"Scale the tone tracks' degrees are drawn from",
),
),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("steps"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(4i64),
maximum: Some(64i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("tempo"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(40i64),
maximum: Some(240i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("tracks"),
LexObjectProperty::Array(LexArray {
description: Some(
CowStr::new_static(
"The overlapping tracks, played together on the loop",
),
),
items: LexArrayItem::Object(LexObject {
required: Some(
vec![
SmolStr::new_static("kind"), SmolStr::new_static("cells")
],
),
properties: {
#[allow(unused_mut)]
let mut map = BTreeMap::new();
map.insert(
SmolStr::new_static("cells"),
LexObjectProperty::Array(LexArray {
description: Some(
CowStr::new_static(
"Interleaved note data: [step, degree-or-piece, ...]",
),
),
items: LexArrayItem::Integer(LexInteger {
..Default::default()
}),
max_length: Some(8192usize),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("gain"),
LexObjectProperty::Integer(LexInteger {
minimum: Some(0i64),
maximum: Some(100i64),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("kind"),
LexObjectProperty::String(LexString {
description: Some(
CowStr::new_static("A pitched voice or a percussion lane"),
),
..Default::default()
}),
);
map.insert(
SmolStr::new_static("muted"),
LexObjectProperty::Boolean(LexBoolean {
..Default::default()
}),
);
map.insert(
SmolStr::new_static("wave"),
LexObjectProperty::String(LexString {
description: Some(
CowStr::new_static("Oscillator shape for a tone track"),
),
..Default::default()
}),
);
map
},
..Default::default()
}),
max_length: Some(32usize),
..Default::default()
}),
);
map
},
..Default::default()
}),
..Default::default()
}),
);
map
},
..Default::default()
}
}
pub mod synth_state {
pub use crate::builder_types::{IsSet, IsUnset, Set, Unset};
#[allow(unused)]
use ::core::marker::PhantomData;
mod sealed {
pub trait Sealed {}
}
/// State trait tracking which required fields have been set
pub trait State: sealed::Sealed {
type CreatedAt;
type Name;
type Steps;
type Tempo;
type Tracks;
}
/// Empty state - all required fields are unset
pub struct Empty(());
impl sealed::Sealed for Empty {}
impl State for Empty {
type CreatedAt = Unset;
type Name = Unset;
type Steps = Unset;
type Tempo = Unset;
type Tracks = Unset;
}
///State transition - sets the `created_at` field to Set
pub struct SetCreatedAt<St: State = Empty>(PhantomData<fn() -> St>);
impl<St: State> sealed::Sealed for SetCreatedAt<St> {}
impl<St: State> State for SetCreatedAt<St> {
type CreatedAt = Set<members::created_at>;
type Name = St::Name;
type Steps = St::Steps;
type Tempo = St::Tempo;
type Tracks = St::Tracks;
}
///State transition - sets the `name` field to Set
pub struct SetName<St: State = Empty>(PhantomData<fn() -> St>);
impl<St: State> sealed::Sealed for SetName<St> {}
impl<St: State> State for SetName<St> {
type CreatedAt = St::CreatedAt;
type Name = Set<members::name>;
type Steps = St::Steps;
type Tempo = St::Tempo;
type Tracks = St::Tracks;
}
///State transition - sets the `steps` field to Set
pub struct SetSteps<St: State = Empty>(PhantomData<fn() -> St>);
impl<St: State> sealed::Sealed for SetSteps<St> {}
impl<St: State> State for SetSteps<St> {
type CreatedAt = St::CreatedAt;
type Name = St::Name;
type Steps = Set<members::steps>;
type Tempo = St::Tempo;
type Tracks = St::Tracks;
}
///State transition - sets the `tempo` field to Set
pub struct SetTempo<St: State = Empty>(PhantomData<fn() -> St>);
impl<St: State> sealed::Sealed for SetTempo<St> {}
impl<St: State> State for SetTempo<St> {
type CreatedAt = St::CreatedAt;
type Name = St::Name;
type Steps = St::Steps;
type Tempo = Set<members::tempo>;
type Tracks = St::Tracks;
}
///State transition - sets the `tracks` field to Set
pub struct SetTracks<St: State = Empty>(PhantomData<fn() -> St>);
impl<St: State> sealed::Sealed for SetTracks<St> {}
impl<St: State> State for SetTracks<St> {
type CreatedAt = St::CreatedAt;
type Name = St::Name;
type Steps = St::Steps;
type Tempo = St::Tempo;
type Tracks = Set<members::tracks>;
}
/// Marker types for field names
#[allow(non_camel_case_types)]
pub mod members {
///Marker type for the `created_at` field
pub struct created_at(());
///Marker type for the `name` field
pub struct name(());
///Marker type for the `steps` field
pub struct steps(());
///Marker type for the `tempo` field
pub struct tempo(());
///Marker type for the `tracks` field
pub struct tracks(());
}
}
/// Builder for constructing an instance of this type.
pub struct SynthBuilder<St: synth_state::State, S: BosStr = DefaultStr> {
_state: PhantomData<fn() -> St>,
_fields: (
Option<Datetime>,
Option<SynthFx<S>>,
Option<S>,
Option<i64>,
Option<S>,
Option<i64>,
Option<i64>,
Option<Vec<Data<S>>>,
),
_type: PhantomData<fn() -> S>,
}
impl Synth<DefaultStr> {
/// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed
pub fn new() -> SynthBuilder<synth_state::Empty, DefaultStr> {
SynthBuilder::new()
}
}
impl<S: BosStr> Synth<S> {
/// Create a new builder for this type
pub fn builder() -> SynthBuilder<synth_state::Empty, S> {
SynthBuilder::builder()
}
}
impl SynthBuilder<synth_state::Empty, DefaultStr> {
/// Create a new builder with all fields unset, using the default string type, if needed
pub fn new() -> Self {
SynthBuilder {
_state: PhantomData,
_fields: (None, None, None, None, None, None, None, None),
_type: PhantomData,
}
}
}
impl<S: BosStr> SynthBuilder<synth_state::Empty, S> {
/// Create a new builder with all fields unset
pub fn builder() -> Self {
SynthBuilder {
_state: PhantomData,
_fields: (None, None, None, None, None, None, None, None),
_type: PhantomData,
}
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::CreatedAt: synth_state::IsUnset,
{
/// Set the `createdAt` field (required)
pub fn created_at(
mut self,
value: impl Into<Datetime>,
) -> SynthBuilder<synth_state::SetCreatedAt<St>, S> {
self._fields.0 = Option::Some(value.into());
SynthBuilder {
_state: PhantomData,
_fields: self._fields,
_type: PhantomData,
}
}
}
impl<St: synth_state::State, S: BosStr> SynthBuilder<St, S> {
/// Set the `fx` field (optional)
pub fn fx(mut self, value: impl Into<Option<SynthFx<S>>>) -> Self {
self._fields.1 = value.into();
self
}
/// Set the `fx` field to an Option value (optional)
pub fn maybe_fx(mut self, value: Option<SynthFx<S>>) -> Self {
self._fields.1 = value;
self
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::Name: synth_state::IsUnset,
{
/// Set the `name` field (required)
pub fn name(mut self, value: impl Into<S>) -> SynthBuilder<synth_state::SetName<St>, S> {
self._fields.2 = Option::Some(value.into());
SynthBuilder {
_state: PhantomData,
_fields: self._fields,
_type: PhantomData,
}
}
}
impl<St: synth_state::State, S: BosStr> SynthBuilder<St, S> {
/// Set the `root` field (optional)
pub fn root(mut self, value: impl Into<Option<i64>>) -> Self {
self._fields.3 = value.into();
self
}
/// Set the `root` field to an Option value (optional)
pub fn maybe_root(mut self, value: Option<i64>) -> Self {
self._fields.3 = value;
self
}
}
impl<St: synth_state::State, S: BosStr> SynthBuilder<St, S> {
/// Set the `scale` field (optional)
pub fn scale(mut self, value: impl Into<Option<S>>) -> Self {
self._fields.4 = value.into();
self
}
/// Set the `scale` field to an Option value (optional)
pub fn maybe_scale(mut self, value: Option<S>) -> Self {
self._fields.4 = value;
self
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::Steps: synth_state::IsUnset,
{
/// Set the `steps` field (required)
pub fn steps(mut self, value: impl Into<i64>) -> SynthBuilder<synth_state::SetSteps<St>, S> {
self._fields.5 = Option::Some(value.into());
SynthBuilder {
_state: PhantomData,
_fields: self._fields,
_type: PhantomData,
}
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::Tempo: synth_state::IsUnset,
{
/// Set the `tempo` field (required)
pub fn tempo(mut self, value: impl Into<i64>) -> SynthBuilder<synth_state::SetTempo<St>, S> {
self._fields.6 = Option::Some(value.into());
SynthBuilder {
_state: PhantomData,
_fields: self._fields,
_type: PhantomData,
}
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::Tracks: synth_state::IsUnset,
{
/// Set the `tracks` field (required)
pub fn tracks(
mut self,
value: impl Into<Vec<Data<S>>>,
) -> SynthBuilder<synth_state::SetTracks<St>, S> {
self._fields.7 = Option::Some(value.into());
SynthBuilder {
_state: PhantomData,
_fields: self._fields,
_type: PhantomData,
}
}
}
impl<St, S: BosStr> SynthBuilder<St, S>
where
St: synth_state::State,
St::CreatedAt: synth_state::IsSet,
St::Name: synth_state::IsSet,
St::Steps: synth_state::IsSet,
St::Tempo: synth_state::IsSet,
St::Tracks: synth_state::IsSet,
{
/// Build the final struct.
pub fn build(self) -> Synth<S> {
Synth {
created_at: self._fields.0.unwrap(),
fx: self._fields.1,
name: self._fields.2.unwrap(),
root: self._fields.3,
scale: self._fields.4,
steps: self._fields.5.unwrap(),
tempo: self._fields.6.unwrap(),
tracks: self._fields.7.unwrap(),
extra_data: Default::default(),
}
}
/// Build the final struct with custom extra_data.
pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Synth<S> {
Synth {
created_at: self._fields.0.unwrap(),
fx: self._fields.1,
name: self._fields.2.unwrap(),
root: self._fields.3,
scale: self._fields.4,
steps: self._fields.5.unwrap(),
tempo: self._fields.6.unwrap(),
tracks: self._fields.7.unwrap(),
extra_data: Some(extra_data),
}
}
}