1#[allow(unused_imports)]
9use alloc::collections::BTreeMap;
10
11#[allow(unused_imports)]
12use core::marker::PhantomData;
13use jacquard_common::CowStr;
14
15#[allow(unused_imports)]
16use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
17use jacquard_common::types::collection::{Collection, RecordError};
18use jacquard_common::types::string::{AtUri, Cid, Datetime};
19use jacquard_common::types::uri::{RecordUri, UriError};
20use jacquard_common::xrpc::XrpcResp;
21use jacquard_derive::{IntoStatic, lexicon};
22use jacquard_lexicon::lexicon::LexiconDoc;
23use jacquard_lexicon::schema::LexiconSchema;
24
25#[allow(unused_imports)]
26use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
27use serde::{Serialize, Deserialize};
28use crate::app_bsky::richtext::facet::Facet;
29use crate::network_slices::tools::Images;
30
31#[lexicon]
32#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
33#[serde(
34 rename_all = "camelCase",
35 rename = "network.slices.tools.bug.comment",
36 tag = "$type"
37)]
38pub struct Comment<'a> {
39 #[serde(skip_serializing_if = "Option::is_none")]
40 #[serde(borrow)]
41 pub attachments: Option<Images<'a>>,
42 #[serde(borrow)]
43 pub body: CowStr<'a>,
44 #[serde(skip_serializing_if = "Option::is_none")]
46 #[serde(borrow)]
47 pub body_facets: Option<Vec<Facet<'a>>>,
48 #[serde(borrow)]
50 pub bug: AtUri<'a>,
51 pub created_at: Datetime,
52 #[serde(skip_serializing_if = "Option::is_none")]
54 #[serde(borrow)]
55 pub parent: Option<AtUri<'a>>,
56}
57
58#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
61#[serde(rename_all = "camelCase")]
62pub struct CommentGetRecordOutput<'a> {
63 #[serde(skip_serializing_if = "Option::is_none")]
64 #[serde(borrow)]
65 pub cid: Option<Cid<'a>>,
66 #[serde(borrow)]
67 pub uri: AtUri<'a>,
68 #[serde(borrow)]
69 pub value: Comment<'a>,
70}
71
72impl<'a> Comment<'a> {
73 pub fn uri(
74 uri: impl Into<CowStr<'a>>,
75 ) -> Result<RecordUri<'a, CommentRecord>, UriError> {
76 RecordUri::try_from_uri(AtUri::new_cow(uri.into())?)
77 }
78}
79
80#[derive(Debug, Serialize, Deserialize)]
83pub struct CommentRecord;
84impl XrpcResp for CommentRecord {
85 const NSID: &'static str = "network.slices.tools.bug.comment";
86 const ENCODING: &'static str = "application/json";
87 type Output<'de> = CommentGetRecordOutput<'de>;
88 type Err<'de> = RecordError<'de>;
89}
90
91impl From<CommentGetRecordOutput<'_>> for Comment<'_> {
92 fn from(output: CommentGetRecordOutput<'_>) -> Self {
93 use jacquard_common::IntoStatic;
94 output.value.into_static()
95 }
96}
97
98impl Collection for Comment<'_> {
99 const NSID: &'static str = "network.slices.tools.bug.comment";
100 type Record = CommentRecord;
101}
102
103impl Collection for CommentRecord {
104 const NSID: &'static str = "network.slices.tools.bug.comment";
105 type Record = CommentRecord;
106}
107
108impl<'a> LexiconSchema for Comment<'a> {
109 fn nsid() -> &'static str {
110 "network.slices.tools.bug.comment"
111 }
112 fn def_name() -> &'static str {
113 "main"
114 }
115 fn lexicon_doc() -> LexiconDoc<'static> {
116 lexicon_doc_network_slices_tools_bug_comment()
117 }
118 fn validate(&self) -> Result<(), ConstraintError> {
119 {
120 let value = &self.body;
121 #[allow(unused_comparisons)]
122 if <str>::len(value.as_ref()) > 10000usize {
123 return Err(ConstraintError::MaxLength {
124 path: ValidationPath::from_field("body"),
125 max: 10000usize,
126 actual: <str>::len(value.as_ref()),
127 });
128 }
129 }
130 {
131 let value = &self.body;
132 {
133 let count = UnicodeSegmentation::graphemes(value.as_ref(), true).count();
134 if count > 3000usize {
135 return Err(ConstraintError::MaxGraphemes {
136 path: ValidationPath::from_field("body"),
137 max: 3000usize,
138 actual: count,
139 });
140 }
141 }
142 }
143 Ok(())
144 }
145}
146
147pub mod comment_state {
148
149 pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
150 #[allow(unused)]
151 use ::core::marker::PhantomData;
152 mod sealed {
153 pub trait Sealed {}
154 }
155 pub trait State: sealed::Sealed {
157 type CreatedAt;
158 type Bug;
159 type Body;
160 }
161 pub struct Empty(());
163 impl sealed::Sealed for Empty {}
164 impl State for Empty {
165 type CreatedAt = Unset;
166 type Bug = Unset;
167 type Body = Unset;
168 }
169 pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>);
171 impl<S: State> sealed::Sealed for SetCreatedAt<S> {}
172 impl<S: State> State for SetCreatedAt<S> {
173 type CreatedAt = Set<members::created_at>;
174 type Bug = S::Bug;
175 type Body = S::Body;
176 }
177 pub struct SetBug<S: State = Empty>(PhantomData<fn() -> S>);
179 impl<S: State> sealed::Sealed for SetBug<S> {}
180 impl<S: State> State for SetBug<S> {
181 type CreatedAt = S::CreatedAt;
182 type Bug = Set<members::bug>;
183 type Body = S::Body;
184 }
185 pub struct SetBody<S: State = Empty>(PhantomData<fn() -> S>);
187 impl<S: State> sealed::Sealed for SetBody<S> {}
188 impl<S: State> State for SetBody<S> {
189 type CreatedAt = S::CreatedAt;
190 type Bug = S::Bug;
191 type Body = Set<members::body>;
192 }
193 #[allow(non_camel_case_types)]
195 pub mod members {
196 pub struct created_at(());
198 pub struct bug(());
200 pub struct body(());
202 }
203}
204
205pub struct CommentBuilder<'a, S: comment_state::State> {
207 _state: PhantomData<fn() -> S>,
208 _fields: (
209 Option<Images<'a>>,
210 Option<CowStr<'a>>,
211 Option<Vec<Facet<'a>>>,
212 Option<AtUri<'a>>,
213 Option<Datetime>,
214 Option<AtUri<'a>>,
215 ),
216 _lifetime: PhantomData<&'a ()>,
217}
218
219impl<'a> Comment<'a> {
220 pub fn new() -> CommentBuilder<'a, comment_state::Empty> {
222 CommentBuilder::new()
223 }
224}
225
226impl<'a> CommentBuilder<'a, comment_state::Empty> {
227 pub fn new() -> Self {
229 CommentBuilder {
230 _state: PhantomData,
231 _fields: (None, None, None, None, None, None),
232 _lifetime: PhantomData,
233 }
234 }
235}
236
237impl<'a, S: comment_state::State> CommentBuilder<'a, S> {
238 pub fn attachments(mut self, value: impl Into<Option<Images<'a>>>) -> Self {
240 self._fields.0 = value.into();
241 self
242 }
243 pub fn maybe_attachments(mut self, value: Option<Images<'a>>) -> Self {
245 self._fields.0 = value;
246 self
247 }
248}
249
250impl<'a, S> CommentBuilder<'a, S>
251where
252 S: comment_state::State,
253 S::Body: comment_state::IsUnset,
254{
255 pub fn body(
257 mut self,
258 value: impl Into<CowStr<'a>>,
259 ) -> CommentBuilder<'a, comment_state::SetBody<S>> {
260 self._fields.1 = Option::Some(value.into());
261 CommentBuilder {
262 _state: PhantomData,
263 _fields: self._fields,
264 _lifetime: PhantomData,
265 }
266 }
267}
268
269impl<'a, S: comment_state::State> CommentBuilder<'a, S> {
270 pub fn body_facets(mut self, value: impl Into<Option<Vec<Facet<'a>>>>) -> Self {
272 self._fields.2 = value.into();
273 self
274 }
275 pub fn maybe_body_facets(mut self, value: Option<Vec<Facet<'a>>>) -> Self {
277 self._fields.2 = value;
278 self
279 }
280}
281
282impl<'a, S> CommentBuilder<'a, S>
283where
284 S: comment_state::State,
285 S::Bug: comment_state::IsUnset,
286{
287 pub fn bug(
289 mut self,
290 value: impl Into<AtUri<'a>>,
291 ) -> CommentBuilder<'a, comment_state::SetBug<S>> {
292 self._fields.3 = Option::Some(value.into());
293 CommentBuilder {
294 _state: PhantomData,
295 _fields: self._fields,
296 _lifetime: PhantomData,
297 }
298 }
299}
300
301impl<'a, S> CommentBuilder<'a, S>
302where
303 S: comment_state::State,
304 S::CreatedAt: comment_state::IsUnset,
305{
306 pub fn created_at(
308 mut self,
309 value: impl Into<Datetime>,
310 ) -> CommentBuilder<'a, comment_state::SetCreatedAt<S>> {
311 self._fields.4 = Option::Some(value.into());
312 CommentBuilder {
313 _state: PhantomData,
314 _fields: self._fields,
315 _lifetime: PhantomData,
316 }
317 }
318}
319
320impl<'a, S: comment_state::State> CommentBuilder<'a, S> {
321 pub fn parent(mut self, value: impl Into<Option<AtUri<'a>>>) -> Self {
323 self._fields.5 = value.into();
324 self
325 }
326 pub fn maybe_parent(mut self, value: Option<AtUri<'a>>) -> Self {
328 self._fields.5 = value;
329 self
330 }
331}
332
333impl<'a, S> CommentBuilder<'a, S>
334where
335 S: comment_state::State,
336 S::CreatedAt: comment_state::IsSet,
337 S::Bug: comment_state::IsSet,
338 S::Body: comment_state::IsSet,
339{
340 pub fn build(self) -> Comment<'a> {
342 Comment {
343 attachments: self._fields.0,
344 body: self._fields.1.unwrap(),
345 body_facets: self._fields.2,
346 bug: self._fields.3.unwrap(),
347 created_at: self._fields.4.unwrap(),
348 parent: self._fields.5,
349 extra_data: Default::default(),
350 }
351 }
352 pub fn build_with_data(
354 self,
355 extra_data: BTreeMap<
356 jacquard_common::deps::smol_str::SmolStr,
357 jacquard_common::types::value::Data<'a>,
358 >,
359 ) -> Comment<'a> {
360 Comment {
361 attachments: self._fields.0,
362 body: self._fields.1.unwrap(),
363 body_facets: self._fields.2,
364 bug: self._fields.3.unwrap(),
365 created_at: self._fields.4.unwrap(),
366 parent: self._fields.5,
367 extra_data: Some(extra_data),
368 }
369 }
370}
371
372fn lexicon_doc_network_slices_tools_bug_comment() -> LexiconDoc<'static> {
373 #[allow(unused_imports)]
374 use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
375 use jacquard_lexicon::lexicon::*;
376 use alloc::collections::BTreeMap;
377 LexiconDoc {
378 lexicon: Lexicon::Lexicon1,
379 id: CowStr::new_static("network.slices.tools.bug.comment"),
380 defs: {
381 let mut map = BTreeMap::new();
382 map.insert(
383 SmolStr::new_static("main"),
384 LexUserType::Record(LexRecord {
385 key: Some(CowStr::new_static("tid")),
386 record: LexRecordRecord::Object(LexObject {
387 required: Some(
388 vec![
389 SmolStr::new_static("bug"), SmolStr::new_static("body"),
390 SmolStr::new_static("createdAt")
391 ],
392 ),
393 properties: {
394 #[allow(unused_mut)]
395 let mut map = BTreeMap::new();
396 map.insert(
397 SmolStr::new_static("attachments"),
398 LexObjectProperty::Union(LexRefUnion {
399 refs: vec![
400 CowStr::new_static("network.slices.tools.defs#images")
401 ],
402 ..Default::default()
403 }),
404 );
405 map.insert(
406 SmolStr::new_static("body"),
407 LexObjectProperty::String(LexString {
408 max_length: Some(10000usize),
409 max_graphemes: Some(3000usize),
410 ..Default::default()
411 }),
412 );
413 map.insert(
414 SmolStr::new_static("bodyFacets"),
415 LexObjectProperty::Array(LexArray {
416 description: Some(
417 CowStr::new_static(
418 "Annotations of body text (mentions and links)",
419 ),
420 ),
421 items: LexArrayItem::Ref(LexRef {
422 r#ref: CowStr::new_static("app.bsky.richtext.facet"),
423 ..Default::default()
424 }),
425 ..Default::default()
426 }),
427 );
428 map.insert(
429 SmolStr::new_static("bug"),
430 LexObjectProperty::String(LexString {
431 description: Some(
432 CowStr::new_static("Reference to the bug report"),
433 ),
434 format: Some(LexStringFormat::AtUri),
435 ..Default::default()
436 }),
437 );
438 map.insert(
439 SmolStr::new_static("createdAt"),
440 LexObjectProperty::String(LexString {
441 format: Some(LexStringFormat::Datetime),
442 ..Default::default()
443 }),
444 );
445 map.insert(
446 SmolStr::new_static("parent"),
447 LexObjectProperty::String(LexString {
448 description: Some(
449 CowStr::new_static(
450 "Optional reference to parent comment for threading",
451 ),
452 ),
453 format: Some(LexStringFormat::AtUri),
454 ..Default::default()
455 }),
456 );
457 map
458 },
459 ..Default::default()
460 }),
461 ..Default::default()
462 }),
463 );
464 map
465 },
466 ..Default::default()
467 }
468}