A better Rust ATProto crate

Codegen incorrectly generated references to a union enum with a lifetime missing a lifetime #24

open
opened by nonbinary.computer

Lexicon:

{
  "lexicon": 1,
  "id": "sh.weaver.notebook.defs",
  "defs": {
    "notebookView": {
      "type": "object",
      "required": ["uri", "cid", "authors", "record", "indexedAt"],

      "properties": {
        "title": { "type": "ref", "ref": "#title" },
        "path": { "type": "ref", "ref": "#path" },
        "tags": { "type": "ref", "ref": "#tags" },
        "uri": { "type": "string", "format": "at-uri" },
        "cid": { "type": "string", "format": "cid" },
        "authors": {
          "type": "array",
          "items": { "type": "ref", "ref": "#authorListView" }
        },
        "permissions": {
          "type": "ref",
          "ref": "#permissionsState"
        },
        "record": { "type": "unknown" },
        "indexedAt": { "type": "string", "format": "datetime" },
        "likeCount": { "type": "integer" },
        "bookmarkCount": { "type": "integer" },
        "subscriberCount": { "type": "integer" },
        "entryCount": { "type": "integer" },
        "viewerLike": { "type": "string", "format": "at-uri" },
        "viewerBookmark": { "type": "string", "format": "at-uri" },
        "viewerSubscription": { "type": "string", "format": "at-uri" },
        "viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" }
      }
    },
    "entryView": {
      "type": "object",
      "required": ["uri", "cid", "authors", "record", "indexedAt"],

      "properties": {
        "title": { "type": "ref", "ref": "#title" },
        "path": { "type": "ref", "ref": "#path" },
        "tags": { "type": "ref", "ref": "#tags" },
        "uri": { "type": "string", "format": "at-uri" },
        "cid": { "type": "string", "format": "cid" },
        "authors": {
          "type": "array",
          "items": { "type": "ref", "ref": "#authorListView" }
        },
        "permissions": {
          "type": "ref",
          "ref": "#permissionsState"
        },
        "record": { "type": "unknown" },
        "renderedView": {
          "type": "ref",
          "ref": "#renderedView"
        },
        "indexedAt": { "type": "string", "format": "datetime" },
        "likeCount": { "type": "integer" },
        "bookmarkCount": { "type": "integer" },
        "viewerLike": { "type": "string", "format": "at-uri" },
        "viewerBookmark": { "type": "string", "format": "at-uri" },
        "viewerReadingProgress": { "type": "ref", "ref": "#readingProgress" }
      }
    },

    "renderedView": {
      "type": "object",
      "required": ["html"],
      "properties": {
        "html": {
          "type": "blob",
          "accept": ["text/html"],
          "maxSize": 1000000
        },
        "css": {
          "type": "blob",
          "accept": ["text/css"],
          "maxSize": 1000000
        }
      },
      "description": "View of a rendered and cached notebook entry"
    },
    "authorListView": {
      "type": "object",
      "required": ["record", "index"],
      "properties": {
        "uri": { "type": "string", "format": "at-uri" },
        "record": {
          "type": "ref",
          "ref": "sh.weaver.actor.defs#profileDataView"
        },
        "index": { "type": "integer" }
      }
    },

    "bookEntryView": {
      "type": "object",
      "description": "An ordered entry in a Weaver notebook.",
      "required": ["entry", "index"],
      "properties": {
        "entry": {
          "type": "ref",
          "ref": "#entryView"
        },
        "index": { "type": "integer" },
        "next": {
          "type": "ref",
          "ref": "#bookEntryRef"
        },
        "prev": {
          "type": "ref",
          "ref": "#bookEntryRef"
        }
      }
    },

    "bookEntryRef": {
      "type": "object",
      "required": ["entry"],
      "properties": {
        "entry": {
          "type": "ref",
          "ref": "#entryView"
        }
      }
    },
    "title": {
      "type": "string",
      "maxLength": 300,
      "description": "The title of the notebook entry."
    },
    "path": {
      "type": "string",
      "maxLength": 100,
      "description": "The path of the notebook."
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 64
      },
      "maxLength": 10,
      "description": "An array of tags associated with the notebook entry. Tags can help categorize and organize entries."
    },
    "contentFormat": {
      "type": "object",
      "description": "The format of the content. This is used to determine how to render the content.",
      "properties": {
        "markdown": {
          "type": "string",
          "description": "The format of the content. This is used to determine how to render the content.",
          "enum": ["commonmark", "gfm", "obsidian", "weaver"],
          "default": "weaver"
        }
      }
    },
    "permissionsState": {
      "type": "object",
      "description": "ACL-style permissions for a resource. Separate from authors (who contributed).",
      "required": ["editors"],
      "properties": {
        "editors": {
          "type": "array",
          "description": "DIDs that can edit this resource",
          "items": { "type": "ref", "ref": "#permissionGrant" }
        },
        "viewers": {
          "type": "array",
          "description": "DIDs that can view (future use)",
          "items": { "type": "ref", "ref": "#permissionGrant" }
        }
      }
    },
    "permissionGrant": {
      "type": "object",
      "description": "A single permission grant. For resource authority: source=resource URI, grantedAt=createdAt. For invitees: source=invite URI, grantedAt=accept createdAt.",
      "required": ["did", "scope", "source", "grantedAt"],
      "properties": {
        "did": { "type": "string", "format": "did" },
        "scope": {
          "type": "string",
          "knownValues": ["direct", "inherited"],
          "description": "direct = this resource (includes authority), inherited = via notebook invite"
        },
        "source": {
          "type": "string",
          "format": "at-uri",
          "description": "For authority: resource URI. For invitees: invite URI"
        },
        "grantedAt": {
          "type": "string",
          "format": "datetime",
          "description": "For authority: record createdAt. For invitees: accept createdAt"
        }
      }
    },
    "feedEntryView": {
      "type": "object",
      "description": "Entry with feed-specific context (discovery reason, notebook context).",
      "required": ["entry"],
      "properties": {
        "entry": { "type": "ref", "ref": "#entryView" },
        "reason": { "type": "ref", "ref": "#feedReason" },
        "notebookContext": { "type": "ref", "ref": "#feedNotebookContext" }
      }
    },
    "feedNotebookContext": {
      "type": "object",
      "description": "Minimal notebook context for feed display.",
      "required": ["uri", "title"],
      "properties": {
        "uri": { "type": "string", "format": "at-uri" },
        "title": { "type": "string" },
        "path": { "type": "string" }
      }
    },
    "feedReason": {
      "type": "union",
      "description": "Why this entry appeared in the feed.",
      "refs": ["#reasonLike", "#reasonBookmark", "#reasonSubscription"]
    },
    "reasonLike": {
      "type": "object",
      "required": ["by", "indexedAt"],
      "properties": {
        "by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
        "indexedAt": { "type": "string", "format": "datetime" }
      }
    },
    "reasonBookmark": {
      "type": "object",
      "required": ["by", "indexedAt"],
      "properties": {
        "by": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
        "indexedAt": { "type": "string", "format": "datetime" }
      }
    },
    "reasonSubscription": {
      "type": "object",
      "required": ["indexedAt"],
      "properties": {
        "indexedAt": { "type": "string", "format": "datetime" }
      }
    },
    "publishedVersionView": {
      "type": "object",
      "description": "A published version of an entry in a collaborator's repo.",
      "required": ["uri", "cid", "publisher", "publishedAt"],
      "properties": {
        "uri": { "type": "string", "format": "at-uri" },
        "cid": { "type": "string", "format": "cid" },
        "publisher": { "type": "ref", "ref": "sh.weaver.actor.defs#profileViewBasic" },
        "publishedAt": { "type": "string", "format": "datetime" },
        "updatedAt": { "type": "string", "format": "datetime" },
        "isCanonical": {
          "type": "boolean",
          "description": "True if this is the 'primary' version (owner's repo)"
        },
        "divergedFrom": {
          "type": "ref",
          "ref": "com.atproto.repo.strongRef",
          "description": "If content differs, the version it diverged from"
        }
      }
    },
    "contentWarning": {
      "type": "string",
      "description": "Author-applied content warning.",
      "knownValues": [
        "violence",
        "graphic-violence",
        "death",
        "major-character-death",
        "sexual-content",
        "explicit-sexual-content",
        "language",
        "substance-use",
        "self-harm",
        "abuse",
        "disturbing-imagery"
      ]
    },
    "contentWarnings": {
      "type": "array",
      "description": "Author-applied content warnings.",
      "maxLength": 10,
      "items": { "type": "ref", "ref": "#contentWarning" }
    },
    "contentRating": {
      "type": "string",
      "description": "Author-applied content rating.",
      "knownValues": ["general", "teen", "mature", "explicit"]
    },
    "chapterView": {
      "type": "object",
      "description": "Hydrated view of a chapter.",
      "required": ["uri", "cid", "notebook", "authors", "record", "indexedAt"],
      "properties": {
        "uri": { "type": "string", "format": "at-uri" },
        "cid": { "type": "string", "format": "cid" },
        "title": { "type": "ref", "ref": "#title" },
        "tags": { "type": "ref", "ref": "#tags" },
        "notebook": { "type": "ref", "ref": "#notebookView" },
        "authors": {
          "type": "array",
          "items": { "type": "ref", "ref": "#authorListView" }
        },
        "record": { "type": "unknown" },
        "entryCount": { "type": "integer" },
        "indexedAt": { "type": "string", "format": "datetime" }
      }
    },
    "chapterEntryView": {
      "type": "object",
      "description": "An entry within a chapter context.",
      "required": ["entry", "index"],
      "properties": {
        "entry": { "type": "ref", "ref": "#entryView" },
        "index": { "type": "integer" },
        "next": { "type": "ref", "ref": "#bookEntryRef" },
        "prev": { "type": "ref", "ref": "#bookEntryRef" }
      }
    },
    "pageView": {
      "type": "object",
      "description": "Hydrated view of a page (entries displayed together).",
      "required": ["uri", "cid", "notebook", "record", "indexedAt"],
      "properties": {
        "uri": { "type": "string", "format": "at-uri" },
        "cid": { "type": "string", "format": "cid" },
        "title": { "type": "ref", "ref": "#title" },
        "tags": { "type": "ref", "ref": "#tags" },
        "notebook": { "type": "ref", "ref": "#notebookView" },
        "record": { "type": "unknown" },
        "entryCount": { "type": "integer" },
        "indexedAt": { "type": "string", "format": "datetime" }
      }
    },
    "readingProgress": {
      "type": "object",
      "description": "Viewer's reading progress (appview-side state, not a record).",
      "properties": {
        "status": {
          "type": "string",
          "knownValues": ["reading", "finished", "abandoned", "want-to-read"]
        },
        "currentEntry": {
          "type": "string",
          "format": "at-uri",
          "description": "Last entry the viewer was reading."
        },
        "percentComplete": {
          "type": "integer",
          "minimum": 0,
          "maximum": 100
        },
        "lastReadAt": { "type": "string", "format": "datetime" },
        "startedAt": { "type": "string", "format": "datetime" },
        "finishedAt": { "type": "string", "format": "datetime" }
      }
    }
  }
}

Generated output:

///Why this entry appeared in the feed.
#[jacquard_derive::open_union]
#[derive(
    serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic,
)]
#[serde(tag = "$type")]
#[serde(bound(deserialize = "'de: 'a"))]
pub enum FeedReason<'a> {
    #[serde(rename = "sh.weaver.notebook.defs#reasonLike")]
    ReasonLike(Box<crate::sh_weaver::notebook::ReasonLike<'a>>),
    #[serde(rename = "sh.weaver.notebook.defs#reasonBookmark")]
    ReasonBookmark(Box<crate::sh_weaver::notebook::ReasonBookmark<'a>>),
    #[serde(rename = "sh.weaver.notebook.defs#reasonSubscription")]
    ReasonSubscription(Box<crate::sh_weaver::notebook::ReasonSubscription<'a>>),
}
...


/// Entry with feed-specific context (discovery reason, notebook context).
#[jacquard_derive::lexicon]
#[derive(
    serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, jacquard_derive::IntoStatic,
)]
#[serde(rename_all = "camelCase")]
pub struct FeedEntryView<'a> {
    #[serde(borrow)]
    pub entry: crate::sh_weaver::notebook::EntryView<'a>,
    #[serde(skip_serializing_if = "std::option::Option::is_none")]
    #[serde(borrow)]
    pub notebook_context: std::option::Option<crate::sh_weaver::notebook::FeedNotebookContext<'a>>,
    #[serde(skip_serializing_if = "std::option::Option::is_none")]
    #[serde(borrow)]
    pub reason: std::option::Option<crate::sh_weaver::notebook::FeedReason>,
}
sign up or login to add to the discussion
Labels

None yet.

assignee
nonbinary.computer
Participants 1
AT URI
at://did:plc:yfvwmnlztr4dwkb7hwz55r2g/sh.tangled.repo.issue/3m7no5ooqax22