Skip to main content

fiberplane_models/
lib.rs

1/*!
2# Fiberplane Models
3
4> Core Models used across Fiberplane
5
6This crate contains a collection of models that are used across the Fiberplane
7products, including but not limited to:
8
9- Notebooks
10  - Notebook Cells
11  - Notebook Operations
12- Providers
13  - Provider Schemas
14- Comments
15- Front Matter Schemas
16- Rich-Text Formatting
17- Templates
18- Views
19- Workspaces
20
21*/
22
23use serde::de::{Error, Unexpected, Visitor};
24use serde::{Deserialize, Deserializer};
25use std::fmt;
26
27pub mod auth;
28pub mod blobs;
29pub mod comments;
30pub mod data_sources;
31pub mod events;
32pub mod files;
33pub mod formatting;
34pub mod front_matter_schemas;
35pub mod integrations;
36pub mod labels;
37pub mod names;
38pub mod notebooks;
39pub mod pagerduty;
40pub mod paging;
41pub mod providers;
42pub mod proxies;
43pub mod query_data;
44pub mod realtime;
45pub mod snippets;
46pub mod sorting;
47pub mod templates;
48pub mod timestamps;
49pub mod tokens;
50pub mod users;
51pub mod utils;
52pub mod views;
53pub mod webhooks;
54pub mod workspaces;
55
56fn debug_print_bytes(bytes: impl AsRef<[u8]>) -> String {
57    let bytes = bytes.as_ref();
58    if bytes.len() > 100 {
59        format!("{}...", String::from_utf8_lossy(&bytes[..100]))
60    } else {
61        String::from_utf8_lossy(bytes).to_string()
62    }
63}
64
65/// Any value that is present is considered Some value, including null
66// https://github.com/serde-rs/serde/issues/984#issuecomment-314143738
67pub(crate) fn deserialize_some<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
68where
69    T: Deserialize<'de>,
70    D: Deserializer<'de>,
71{
72    Deserialize::deserialize(deserializer).map(Some)
73}
74
75// workaround for "invalid type: string "1", expected u32" bug in query string:
76// - https://linear.app/fiberplane/issue/FP-3066#comment-59e010ae
77// - https://github.com/tokio-rs/axum/discussions/1359
78// use on struct like this: #[serde(deserialize_with = "crate::deserialize_u32")]
79pub(crate) fn deserialize_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D::Error> {
80    deserializer.deserialize_str(U32Visitor)
81}
82
83struct U32Visitor;
84
85impl<'de> Visitor<'de> for U32Visitor {
86    type Value = u32;
87
88    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
89        formatter.write_str("an u32")
90    }
91
92    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
93    where
94        E: Error,
95    {
96        Ok(v)
97    }
98
99    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
100    where
101        E: Error,
102    {
103        v.parse()
104            .map_err(|_| Error::invalid_type(Unexpected::Str(v), &self))
105    }
106
107    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
108    where
109        E: Error,
110    {
111        v.parse()
112            .map_err(|_| Error::invalid_type(Unexpected::Str(v), &self))
113    }
114
115    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
116    where
117        E: Error,
118    {
119        v.parse()
120            .map_err(|_| Error::invalid_type(Unexpected::Str(&v), &self))
121    }
122}
123
124/// Helper trait to use as a trait bound on generic types that must be serializable when
125/// the `fp-bindgen` feature is enabled
126pub trait BindgenSerializable {}
127
128#[cfg(feature = "fp-bindgen")]
129impl<T> BindgenSerializable for T where
130    T: fp_bindgen::prelude::Serializable + for<'de> serde::de::Deserialize<'de>
131{
132}
133
134#[cfg(not(feature = "fp-bindgen"))]
135impl<T> BindgenSerializable for T {}