Skip to main content

sbol/
lib.rs

1//! Rust support for the Synthetic Biology Open Language (SBOL) 3.1.0
2//! specification.
3//!
4//! The crate keeps RDF parsing and serialization behind a small adapter while
5//! exposing SBOL documents, typed builders, owned typed client objects, and
6//! structured validation diagnostics.
7//!
8//! ```
9//! use sbol::constants::SBO_DNA;
10//! use sbol::prelude::*;
11//!
12//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
13//! let component = Component::builder("https://example.org/lab", "my_component")?
14//!     .types([SBO_DNA])
15//!     .name("My component")
16//!     .build()?;
17//!
18//! let document = Document::from_objects(vec![SbolObject::Component(component)])?;
19//! document.check()?;
20//!
21//! assert_eq!(document.components().count(), 1);
22//! # Ok(())
23//! # }
24//! ```
25//!
26//! # Mental model
27//!
28//! SBOL describes designed biology as a graph of typed objects. Every object
29//! has a stable [`Iri`] identity, a `displayId`, and a namespace. Objects
30//! split into two layers:
31//!
32//! - **Top-level objects** live directly in a [`Document`]:
33//!   [`Component`] (the central design unit — DNA, RNA, protein, complexes,
34//!   functional descriptions), [`Sequence`], [`Collection`],
35//!   [`CombinatorialDerivation`], [`Implementation`], [`ExperimentalData`],
36//!   [`Experiment`], [`Model`], [`Attachment`], plus PROV-O activities
37//!   ([`Activity`], [`Plan`], [`Agent`]) and OM unit definitions ([`Unit`]
38//!   and friends).
39//! - **Owned children** belong to a top-level parent and live nested inside
40//!   it: [`SubComponent`] / [`LocalSubComponent`] /
41//!   [`ExternallyDefined`] / [`SequenceFeature`] / [`ComponentReference`]
42//!   hang off [`Component`]; [`Range`] / [`Cut`] / [`EntireSequence`] hang
43//!   off features; [`Interaction`]s contain [`Participation`]s;
44//!   [`Constraint`]s relate features.
45//!
46//! References between objects are typed: a [`SubComponent`] names the
47//! [`Component`] it instantiates, an [`ExternallyDefined`] points to a term in
48//! an external ontology, and so on. Reference traversal lives on the typed
49//! structs and takes anything implementing [`ObjectGraph`] — a [`Document`]
50//! for single-file work, a [`DocumentSet`] when references cross document
51//! boundaries.
52//!
53//! # Document lifecycle
54//!
55//! A typical flow:
56//!
57//! 1. **Read.** [`Document::read_path`] infers the format from the file
58//!    extension; [`Document::read`] takes an explicit [`RdfFormat`] for
59//!    in-memory input.
60//! 2. **Validate.** [`Document::validate`] returns a full
61//!    [`ValidationReport`] with errors, warnings, and per-rule coverage —
62//!    use it when you want to inspect or render the report regardless of
63//!    pass/fail state. [`Document::check`] is the `?`-friendly convenience
64//!    that maps errors to `Err` (warnings ignored), and
65//!    [`Document::check_complete`] additionally fails on
66//!    partial-application diagnostics for strict CI gates.
67//! 3. **Traverse / mutate.** Typed accessors on [`Document`] iterate each
68//!    top-level class (`document.components()`, `document.sequences()`,
69//!    `document.activities()`, …). Builders ([`Component::builder`], etc.)
70//!    construct new objects without invalidating existing IRIs.
71//! 4. **Write.** [`Document::write`] takes an [`RdfFormat`];
72//!    `write_turtle`, `write_rdf_xml`, `write_jsonld`, and `write_ntriples`
73//!    are shortcut methods. Round-trip preserves unknown extension triples.
74//!
75//! # Error model
76//!
77//! Errors are surfaced through four distinct types so callers can branch on
78//! the failure mode without parsing strings:
79//!
80//! - [`ReadError`] — I/O or parse failure when ingesting RDF.
81//! - [`BuildError`] — invariant violation at builder time (invalid
82//!   `displayId`, malformed namespace, missing required field).
83//! - [`WriteError`] — serialization failure.
84//! - [`ValidationReport`] — structured diagnostics from validation
85//!   (multiple issues per call, each with its `sbol3-*` rule identifier).
86//!
87//! # Where to go next
88//!
89//! - **[Crate guide](https://github.com/marpaia/sbol-rs/blob/master/docs/crate-guide.md)** —
90//!   architectural tour and where each subsystem lives.
91//! - **[Validation system overview](https://github.com/marpaia/sbol-rs/blob/master/docs/validation.md)** —
92//!   what the validator covers, `check` vs `check_complete`, CI wiring,
93//!   trust boundaries.
94//! - **[RDF I/O](https://github.com/marpaia/sbol-rs/blob/master/docs/rdf-io.md)** —
95//!   format inference, round-trip guarantees, cross-implementation
96//!   conformance.
97//! - **[Conformance grid](https://github.com/marpaia/sbol-rs/blob/master/docs/conformance.md)** —
98//!   generated per-rule status for every SBOL 3.1.0 rule.
99//! - **[`prelude`]** — re-exports the symbols you'll need for most code;
100//!   `use sbol::prelude::*;` is the conventional import. It includes the
101//!   [`SbolIdentified`] and [`SbolTopLevel`] accessor traits so methods
102//!   like `component.name()`, `component.display_id()`, and
103//!   `component.namespace()` are available on every typed object.
104//! - **[`constants`]** — IRIs for SBO / SO / EDAM / SBOL terms that show up
105//!   as builder arguments (`SBO_DNA`, `SO_PROMOTER`, etc.).
106
107#![forbid(unsafe_code)]
108// `check`/`check_complete` deliberately return the full ValidationReport in
109// both Ok and Err arms so callers always get the report; boxing the Err arm
110// would split that surface.
111#![allow(clippy::result_large_err)]
112
113mod client;
114mod conformance;
115pub mod constants;
116mod document;
117pub mod downgrade;
118mod error;
119pub mod identity;
120mod iri_util;
121mod model;
122mod object;
123pub mod owl_conformance;
124pub mod prelude;
125mod resolve;
126mod sbol2_vocab;
127pub mod schema;
128mod specification;
129pub mod upgrade;
130mod validation;
131mod vocab;
132
133pub use client::{
134    Activity, ActivityBuilder, Agent, AgentBuilder, Association, AssociationBuilder, Attachment,
135    AttachmentBuilder, BinaryPrefix, BinaryPrefixBuilder, Collection, CollectionBuilder,
136    CombinatorialDerivation, CombinatorialDerivationBuilder, Component, ComponentBuilder,
137    ComponentReference, ComponentReferenceBuilder, CompoundUnit, CompoundUnitBuilder, Constraint,
138    ConstraintBuilder, Cut, CutBuilder, EntireSequence, EntireSequenceBuilder, Experiment,
139    ExperimentBuilder, ExperimentalData, ExperimentalDataBuilder, ExtensionTriple,
140    ExternallyDefined, ExternallyDefinedBuilder, FeatureData, FeatureRef, IdentifiedData,
141    IdentifiedExtension, IdentifiedExtensionBuilder, Implementation, ImplementationBuilder,
142    Interaction, InteractionBuilder, Interface, InterfaceBuilder, LocalSubComponent,
143    LocalSubComponentBuilder, LocationData, LocationRef, Measure, MeasureBuilder, Model,
144    ModelBuilder, Participation, ParticipationBuilder, Plan, PlanBuilder, Prefix, PrefixBuilder,
145    PrefixData, PrefixedUnit, PrefixedUnitBuilder, Range, RangeBuilder, SIPrefix, SIPrefixBuilder,
146    SbolIdentified, SbolObject, SbolTopLevel, Sequence, SequenceBuilder, SequenceFeature,
147    SequenceFeatureBuilder, SingularUnit, SingularUnitBuilder, SubComponent, SubComponentBuilder,
148    ToRdf, TopLevelData, TryFromObject, Unit, UnitBuilder, UnitData, UnitDivision,
149    UnitDivisionBuilder, UnitExponentiation, UnitExponentiationBuilder, UnitMultiplication,
150    UnitMultiplicationBuilder, Usage, UsageBuilder, VariableFeature, VariableFeatureBuilder,
151};
152pub use conformance::render_conformance_report;
153pub use document::{Document, UpgradeFromPathError};
154pub use downgrade::{
155    DowngradeCounts, DowngradeError, DowngradeOptions, DowngradeReport, DowngradeWarning,
156    sbol3_to_sbol2,
157};
158pub use error::{BuildError, ReadError, WriteError};
159pub use identity::{DisplayId, HashAlgorithm, Namespace, SbolIdentity, SequenceElements};
160pub use model::{Identified, SbolClass, TopLevel};
161pub use object::Object;
162pub use owl_conformance::{
163    OWL_ONLY_ALLOWLIST, OwlConformanceReport, OwlIdentifiers, OwlPinInfo, RUST_ONLY_ALLOWLIST,
164    analyze_owl_conformance, extract_owl_identifiers, extract_vocab_iris,
165    render_owl_conformance_report,
166};
167pub use resolve::{FeatureTrace, ObjectGraph, ReferenceError, VariantSet};
168pub use sbol_ontology::{Ontology, OntologyRegistry};
169pub use sbol_rdf::{Graph as RdfGraph, Iri, Literal, RdfFormat, Resource, Term, Triple};
170pub use specification::{SPEC_VERSION, SPECIFICATION_URL};
171pub use upgrade::{
172    MapsToSide, NamespaceSource, UpgradeCounts, UpgradeError, UpgradeOptions, UpgradeReport,
173    UpgradeWarning, parse_and_upgrade, sbol2_to_sbol3,
174};
175#[cfg(feature = "http-resolver")]
176pub use validation::CachingHttpResolver;
177#[cfg(feature = "http-resolver")]
178pub use validation::HttpResolver;
179pub use validation::{
180    AppliedOptions, Blocker, ContentResolver, CoverageKind, DocumentResolver, DocumentSet,
181    DocumentSetError, ExternalValidationMode, FileResolver, HashAlgorithmRegistry, Hint,
182    NormativeSeverity, NotApplied, NotAppliedReason, PartialApplication, PolicyOptions,
183    ResolutionError, ResolutionErrorKind, ResolvedContent, RuleCoverage, RuleOverride, RuleStatus,
184    Severity, TopologyCompleteness, UnknownRule, VALIDATION_OUTPUT_SCHEMA_VERSION,
185    VALIDATION_RULE_SPEC_CANONICAL_URL, VALIDATION_RULE_SPEC_PATH, VALIDATION_RULE_SPEC_PDF_SHA256,
186    VALIDATION_RULE_SPEC_VERSION, ValidationContext, ValidationIssue, ValidationOptions,
187    ValidationReport, ValidationRuleStatus, to_json, validation_rule_statuses,
188};