use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformPoint {
pub x: f64,
pub y: f64,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformSize {
pub width: f64,
pub height: f64,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformTransform {
pub a: f64,
pub b: f64,
pub c: f64,
pub d: f64,
pub tx: f64,
pub ty: f64,
}
impl Default for FreeformTransform {
fn default() -> Self {
Self { a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: 0.0, ty: 0.0 }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformFrame {
pub x: f64,
pub y: f64,
pub w: f64,
pub h: f64,
pub rotation: f64,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformGeometry {
pub frame: Option<FreeformFrame>,
pub transform: Option<FreeformTransform>,
pub anchor: Option<FreeformPoint>,
pub horizontal_flip: Option<bool>,
pub vertical_flip: Option<bool>,
pub width_valid: Option<bool>,
pub height_valid: Option<bool>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformColor {
pub color_space: String,
pub red: f64,
pub green: f64,
pub blue: f64,
pub alpha: f64,
pub hex: String,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformGradientStop {
pub fraction: f64,
pub inflection: Option<f64>,
pub color: FreeformColor,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "kind", rename_all = "camelCase", rename_all_fields = "camelCase")
)]
pub enum FreeformPaint {
Solid { color: FreeformColor },
LinearGradient {
start: FreeformPoint,
end: FreeformPoint,
stops: Vec<FreeformGradientStop>,
},
RadialGradient {
center: FreeformPoint,
radius: f64,
stops: Vec<FreeformGradientStop>,
},
Image {
asset_id: String,
technique: Option<String>,
},
Unknown { raw_data: Vec<u8> },
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformStrokeStyle {
pub paint: FreeformPaint,
pub width: f64,
pub dash: Vec<f64>,
pub dash_offset: Option<f64>,
pub cap: Option<String>,
pub join: Option<String>,
pub miter_limit: Option<f64>,
pub tail_end: Option<String>,
pub head_end: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformShadow {
pub kind: String,
pub color: FreeformColor,
pub offset_x: f64,
pub offset_y: f64,
pub radius: f64,
pub opacity: Option<f64>,
pub angle: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformStyle {
pub opacity: Option<f64>,
pub fill: Option<FreeformPaint>,
pub stroke: Option<FreeformStrokeStyle>,
pub shadows: Vec<FreeformShadow>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub enum FreeformInkPointRole {
SplineControl,
RenderedSample,
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformInkPoint {
pub x: f64,
pub y: f64,
pub time_offset: Option<f64>,
pub width: Option<f64>,
pub height: Option<f64>,
pub opacity: Option<f64>,
pub force: Option<f64>,
pub azimuth: Option<f64>,
pub altitude: Option<f64>,
pub secondary_scale: Option<f64>,
pub threshold: Option<f64>,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformInkRange {
pub start: f64,
pub end: f64,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformInkStroke {
pub ink_type: String,
pub ink_identifier: String,
pub color: Option<FreeformColor>,
pub transform: FreeformTransform,
pub point_role: FreeformInkPointRole,
pub points: Vec<FreeformInkPoint>,
pub visible_ranges: Option<Vec<FreeformInkRange>>,
pub random_seed: Option<u32>,
pub raw_data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformDrawing {
pub required_content_version: Option<u32>,
pub bounds: Option<FreeformFrame>,
pub strokes: Vec<FreeformInkStroke>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "kind", rename_all = "camelCase", rename_all_fields = "camelCase")
)]
pub enum FreeformPathCommand {
Move { point: FreeformPoint },
Line { point: FreeformPoint },
Quadratic { control: FreeformPoint, point: FreeformPoint },
Cubic {
control_1: FreeformPoint,
control_2: FreeformPoint,
point: FreeformPoint,
},
Close,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformPath {
pub commands: Vec<FreeformPathCommand>,
pub natural_size: Option<FreeformSize>,
pub raw_data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "kind", content = "value", rename_all = "camelCase")
)]
pub enum TsuValue {
Null,
Bool(bool),
Integer(i64),
Real(f64),
String(String),
Data(Vec<u8>),
Array(Vec<Self>),
Dictionary(BTreeMap<String, Self>),
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct TsuEntry {
pub class_name: String,
pub hints: BTreeMap<String, TsuValue>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformTextRun {
pub start: usize,
pub end: usize,
pub font_name: Option<String>,
pub font_size: Option<f64>,
pub bold: Option<bool>,
pub italic: Option<bool>,
pub underline: Option<String>,
pub strikethrough: Option<String>,
pub fill: Option<FreeformPaint>,
pub paragraph_alignment: Option<String>,
pub writing_direction: Option<String>,
pub hyperlink: Option<String>,
pub list_style: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformText {
pub plain: String,
pub runs: Vec<FreeformTextRun>,
pub inset: Option<FreeformFrame>,
pub vertical_alignment: Option<String>,
pub shrink_to_fit: Option<bool>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformConnectorEndpoint {
pub item_id: Option<String>,
pub magnet: Option<String>,
pub normalized_position: Option<FreeformPoint>,
pub point: Option<FreeformPoint>,
pub line_end: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformTableCell {
pub id: Option<String>,
pub row: Option<usize>,
pub column: Option<usize>,
pub row_span: Option<usize>,
pub column_span: Option<usize>,
pub style: FreeformStyle,
pub text: Option<FreeformText>,
pub anchored_item_ids: Vec<String>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformAsset {
pub id: String,
pub filename: Option<String>,
pub uti: Option<String>,
pub bytes: Option<Vec<u8>>,
pub premium: Option<bool>,
pub intrinsic_size: Option<FreeformSize>,
pub raw_descriptor: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "kind", rename_all = "camelCase", rename_all_fields = "camelCase")
)]
pub enum FreeformItemKind {
Shape { preset: Option<String>, path: Option<FreeformPath> },
TextBox { text: Option<FreeformText> },
StickyNote { text: Option<FreeformText> },
Connector {
tail: FreeformConnectorEndpoint,
head: FreeformConnectorEndpoint,
routing: Option<String>,
path: Option<FreeformPath>,
},
Table {
row_heights: Vec<f64>,
column_widths: Vec<f64>,
cells: Vec<FreeformTableCell>,
},
Image {
asset_id: Option<String>,
crop: Option<FreeformFrame>,
mask: Option<FreeformPath>,
},
Media { asset_id: Option<String>, media_type: Option<String> },
File { asset_id: Option<String>, filename: Option<String> },
Url { url: Option<String>, title: Option<String> },
Usdz { asset_id: Option<String>, spatial_transform: Option<Vec<f64>> },
Group {
child_ids: Vec<String>,
counter_transform: Option<FreeformTransform>,
},
Ink { strokes: Vec<FreeformInkStroke> },
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformRecordRange {
pub offset: usize,
pub length: usize,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformBoardItem {
pub index: usize,
pub uuid: String,
pub parent_id: Option<String>,
pub class_name: Option<String>,
pub hints: BTreeMap<String, TsuValue>,
pub geometry: FreeformGeometry,
pub style: FreeformStyle,
pub kind: FreeformItemKind,
pub record_ranges: Vec<FreeformRecordRange>,
pub raw_data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "kind", rename_all = "camelCase", rename_all_fields = "camelCase")
)]
pub enum FreeformCompatibility {
#[default]
Unknown,
Supported { version: u64 },
Unsupported { minimum_version: u64 },
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformNative {
pub paste_id: String,
pub compatibility: FreeformCompatibility,
pub items: Vec<FreeformBoardItem>,
pub assets: BTreeMap<String, FreeformAsset>,
pub raw_manifest: Vec<u8>,
pub raw_index: Vec<u8>,
pub raw_archive: Vec<u8>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub enum FreeformDecodeErrorKind {
Invalid,
Incomplete,
UnsupportedVersion,
CorrelationMismatch,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformDecodeError {
pub kind: FreeformDecodeErrorKind,
pub message: String,
}
impl FreeformDecodeError {
pub fn invalid(message: impl Into<String>) -> Self {
Self { kind: FreeformDecodeErrorKind::Invalid, message: message.into() }
}
pub fn incomplete(message: impl Into<String>) -> Self {
Self { kind: FreeformDecodeErrorKind::Incomplete, message: message.into() }
}
pub fn unsupported(message: impl Into<String>) -> Self {
Self { kind: FreeformDecodeErrorKind::UnsupportedVersion, message: message.into() }
}
pub fn correlation(message: impl Into<String>) -> Self {
Self { kind: FreeformDecodeErrorKind::CorrelationMismatch, message: message.into() }
}
}
impl std::fmt::Display for FreeformDecodeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "freeform decode: {}", self.message)
}
}
impl std::error::Error for FreeformDecodeError {}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(tag = "status", content = "value", rename_all = "camelCase")
)]
#[derive(Default)]
pub enum FreeformTier<T> {
#[default]
Absent,
Decoded(T),
Failed(FreeformDecodeError),
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformFlavor {
pub uti: String,
pub bytes: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformBlobs {
pub change_count: Option<i64>,
pub flavors: Vec<FreeformFlavor>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformNativeMetadata {
pub paste_id: Option<String>,
pub raw_data: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformRender {
pub uti: String,
pub bytes: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformDiagnostic {
pub source: String,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct FreeformPasteboard {
pub drawing: FreeformTier<FreeformDrawing>,
pub native: FreeformTier<FreeformNative>,
pub manifest: FreeformTier<Vec<TsuEntry>>,
pub metadata: FreeformTier<FreeformNativeMetadata>,
pub assets: BTreeMap<String, FreeformAsset>,
pub renders: Vec<FreeformRender>,
pub state: BTreeMap<String, Vec<u8>>,
pub styles: Vec<FreeformFlavor>,
pub text: Vec<FreeformFlavor>,
pub unknown_flavors: Vec<FreeformFlavor>,
pub diagnostics: Vec<FreeformDiagnostic>,
}