Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions docs/context-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ auto context = c2pa::Context::ContextBuilder()
| `with_signer(signer)` | Store a `Signer` in the context (consumed; used by `Builder::sign` with no explicit signer) |
| `with_progress_callback(callback)` | Register a progress/cancel callback (see [Progress callbacks and cancellation](#progress-callbacks-and-cancellation)) |
| `create_context()` | Build and return the `Context` (consumes the builder) |
| `release()` | Release the raw `C2paContextBuilder*` together with its progress-callback heap owner (see also [Releasing to a custom IContextProvider](#releasing-to-a-custom-icontextprovider)) |
| `release()` | Release the raw `C2paContextBuilder*` together with its progress and in-place signer callback owners (see also [Releasing to a custom IContextProvider](#releasing-to-a-custom-icontextprovider)) |

## Progress callbacks and cancellation

Expand Down Expand Up @@ -883,7 +883,7 @@ c2pa::Context context(R"({

## Migrating from deprecated APIs

The SDK introduced Context-based APIs to replace constructors and functions that relied on thread-local state. The older APIs still compile but produce deprecation warnings. This section covers each deprecation that involves passing a `Context`, and explains the `Builder::sign` overloads.
The SDK introduced Context-based APIs to replace constructors and functions that relied on thread-local state. `load_settings` has been removed; the older Reader and Builder constructors remain deprecated and now use default Contexts. This section covers migration to an explicit `Context`, and explains the `Builder::sign` overloads.

### Quick reference

Expand All @@ -898,7 +898,7 @@ The SDK introduced Context-based APIs to replace constructors and functions that

### Replacing load_settings

`c2pa::load_settings(data, format)` sets thread-local settings that `Reader` and `Builder` pick up implicitly. Replace it with a `Context` that you pass explicitly.
The removed `c2pa::load_settings(data, format)` function set thread-local settings that `Reader` and `Builder` picked up implicitly. Replace it with a `Context` that you pass explicitly.

| Aspect | load_settings (legacy) | Context |
|--------|------------------------|---------|
Expand Down Expand Up @@ -986,14 +986,28 @@ External libraries can implement `IContextProvider` to supply their own context

#### Releasing to a custom IContextProvider

`Context::ContextBuilder::release()` hands off both the native `C2paContextBuilder*` and the heap-owned progress callback (if any) to the caller. It is the entry point when application code needs to build the native context directly or adopt it into a custom `IContextProvider` implementation.
`Context::ContextBuilder::release()` hands off the native `C2paContextBuilder*`
and both heap-owned callbacks (if any) to the caller. It is the entry point
when application code needs to build the native context directly or adopt it
into a custom `IContextProvider` implementation.

`ReleasedBuilder` exposes two fields:
`ReleasedBuilder` exposes three fields:

- `builder`: the raw `C2paContextBuilder*`. It must be passed to `c2pa_context_builder_build` exactly once.
- `callback_owner`: `std::unique_ptr<c2pa::ProgressCallbackFunc>`; `nullptr` when no progress callback was set. When non-null, it must remain alive at least as long as the native context built from `builder`. If it is destroyed earlier, the library will dereference freed memory on the next progress tick.

When the built-in `Context` is sufficient, `create_context()` is preferred. It performs the same handoff internally and keeps the native handle and callback owner bound together.
- `signer_callback_owner`: `std::unique_ptr<c2pa::SignerIntoFunc>`; `nullptr`
unless an in-place callback signer was set. Keep it alive until all native
objects using the signer, including contexts and derived Builders, are
freed. Free native objects before destroying either callback owner.

To adopt the result into the built-in Context, pass both owners to
`Context(native_context, std::move(released.callback_owner),
std::move(released.signer_callback_owner))` after successfully building the
native context. Do not drop the third field when adapting an older provider.

When the built-in `Context` is sufficient, `create_context()` is preferred. It
performs the same handoff internally and keeps the native handle and both
callback owners bound together.

### Builder::sign overloads

Expand Down
13 changes: 10 additions & 3 deletions docs/embeddable-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,25 @@ These methods perform the signing workflow: placeholder creation, hashing, and s
| `Builder::update_hash_from_stream(format, stream)` | Reads the asset stream and computes the hard-binding hash. Automatically selects the appropriate path based on format: `BmffHash` for BMFF (skips manifest box), `BoxHash` for chunk-based formats (creates assertion if needed), or `DataHash` (skips exclusion ranges). Takes a `std::istream&`. |
| `Builder::sign_embeddable(format)` | Signs the manifest and returns bytes ready to embed. For placeholder workflows, it pads the output to match the placeholder size for in-place patching. For BoxHash workflows, the output is the actual signed manifest size (not padded), suitable for appending as a new chunk. |

### Deprecated methods
### Removed methods

The c2pa-rs 0.92.0 removes C FFI functions behind some `Builder` methods. These methods will be removed when c2pa-c moves to c2pa-rs 0.92.0.
The following deprecated methods have been removed to support c2pa-rs 0.92.0,
which removes their underlying C FFI functions.

| Deprecated method | Replacement |
| Removed method | Replacement |
|-------------------|-------------|
| `data_hashed_placeholder(reserved_size, format)` | `needs_placeholder(format)`, then `placeholder(format)`. The reserve size comes from the signer on the Context. |
| `sign_data_hashed_embeddable(signer, data_hash, format, asset)` | `set_data_hash_exclusions(exclusions)`, `update_hash_from_stream(format, stream)`, then `sign_embeddable(format)`. The signer comes from the Context. |
| `format_embeddable(format, data)` | `sign_embeddable(format)`, which returns bytes already formatted for `format`. |

For the full replacement flow, see [Using the DataHash placeholder](#using-the-datahash-placeholder).

Attach the signer to the `Context` before constructing the `Builder`; the
placeholder's reserve size and signing operation both use that signer.
For a precomputed hash, include a `c2pa.hash.data` assertion in the manifest
definition, then call `sign_embeddable(format)` directly without creating a
placeholder or hashing an asset stream.

## Using the DataHash placeholder

Use this workflow for JPEG, PNG, and other non-BMFF formats.
Expand Down
3 changes: 1 addition & 2 deletions docs/intents.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ You can set the intent on a `Builder` instance by:
- [Using Context](#using-context)
- [Using `set_intent` on the `Builder`](#using-set_intent-on-builder)

Don't set intent using the deprecated `load_settings()` function. For existing code, see [Context and Settings - Migrating from deprecated APIs](context-settings.md#migrating-from-deprecated-apis).
The deprecated `load_settings()` function has been removed. For existing code, see [Context and Settings - Migrating from deprecated APIs](context-settings.md#migrating-from-deprecated-apis).

### Using Context

Expand Down Expand Up @@ -485,4 +485,3 @@ c2pa::Builder builder(context, R"({})");
builder.set_intent(Update);
builder.sign("signed_asset.jpg", "updated_asset.jpg", signer);
```

33 changes: 32 additions & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Release notes

## Unreleased

### Zero-copy C++ APIs

- Added move-only `ByteBuffer`, read-only and mutable byte views, and
`sign_to_buffer` siblings for all five signing overloads, plus
`placeholder_to_buffer` and `sign_embeddable_to_buffer`. Existing vector
APIs retain their signatures and copy explicitly through the owning buffer.
- Added capturing `SignerIntoFunc` callbacks that borrow native input/output
buffers directly. Heap-owned callback state survives moves and transfers
into Contexts; `ReleasedBuilder` now carries a `signer_callback_owner`
field that custom providers must retain. See [usage and ownership](usage.md).
- Documented direct stream-buffer forwarding and deferred native release of
HTTP response bodies.

### Breaking changes

- Removed deprecated `Builder::data_hashed_placeholder`,
`Builder::sign_data_hashed_embeddable`, and `Builder::format_embeddable`
for compatibility with c2pa-rs 0.92.0. Use the context-signer workflow in
[Embeddable manifests](embeddable-api.md#removed-methods).
- Removed deprecated `c2pa::load_settings`. Configure each `Context` using
`Settings` or `Context::ContextBuilder` instead; settings are no longer
thread-global.
- Stream wrappers now hold opaque `C2paStream` handles rather than inheriting
from the C struct. Use their existing `c_stream` member when calling the C
API, and rebuild C++ consumers against the updated headers.

Non-deprecated method names and signatures are unchanged. Development uses a
local Rust source build; the default prebuilt-library version has not yet
been updated.

## 3 Mar 2026

This release includes changes relating to trust validation and handling (made in the Rust library [v0.68.0](https://github.com/contentauth/c2pa-rs/releases/tag/c2pa-v0.68.0), see also [trust lists](https://opensource.contentauthenticity.org/docs/conformance/trust-lists) for more details on trust lists).
Expand All @@ -10,4 +42,3 @@ Additionally, this release adds support for:
- Using `Builder` and `Reader` together to [selectively construct a manifest by filtering actions and ingredients](selective-manifests.md).

For answers to frequently asked questions about these features, see the [FAQs](faqs.md).

62 changes: 62 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,68 @@ To use this library, include the header file in your code as follows:
#include "c2pa.hpp"
```

## Native byte buffers without a copy

Every `Builder::sign` overload has a `sign_to_buffer` sibling with the same
arguments. `placeholder_to_buffer(format)` and
`sign_embeddable_to_buffer(format)` similarly mirror the embeddable APIs.
These return a move-only `c2pa::ByteBuffer` that owns the native allocation
without copying it into a C++ vector:

```cpp
c2pa::ByteBuffer manifest = builder.sign_to_buffer("image/jpeg", source, dest);
c2pa::ConstBytes view = manifest.view();
// Consume view.data[0..view.size) while manifest owns the allocation.
auto copied = manifest.to_vector(); // Explicit, optional copy.
```

`data()`, `size()`, `empty()`, `begin()`, and `end()` provide read-only access.
Moving a buffer preserves its allocation address and empties the source.
Destruction or move-assignment over the owner invalidates its views and frees
the allocation exactly once with `c2pa_free`. Do not modify, `free`, `realloc`,
or call `c2pa_free` on `data()` yourself. The buffer may outlive its Builder.
An empty buffer may have a null `data()` pointer; do not dereference it.
Existing vector-returning methods keep their signatures and make an explicit
copy from the same owning buffer internally.

## In-place signing callbacks

The `Signer(SignerIntoFunc, alg, certs, tsa_uri)` overload accepts capturing
callables. Its `ConstBytes` input views the native payload and its
`MutableBytes` output views the native signature destination. An application's
crypto or HSM backend can write directly into that destination, eliminating
the vector-based callback's input and output copies.

The callable must write no more than `signature.size` bytes, return the actual
number written, or return a negative value on failure. The wrapper rejects
oversized counts and converts exceptions to an I/O error before returning to
the C API. A short or invalid cryptographic signature fails signing; returning
a small count is not a way to truncate a signature. Never retain either view
after the callback returns. Captured state must be safe for concurrent calls.

The callable is heap-owned at a stable address across Signer moves. Passing
the signer to `ContextBuilder::with_signer` transfers the callable along with
the native signer to the resulting Context. Prefer a `shared_ptr<Context>`
when constructing Builders so that their callback owner remains alive.
Custom providers using `ContextBuilder::release()` must keep its
`signer_callback_owner` alive until every native object using that signer is
freed; see [Context ownership](context-settings.md#releasing-to-a-custom-icontextprovider).
The existing vector-based `SignerFunc` constructor remains available.

## Stream and HTTP callback ownership

`CppIStream`, `CppOStream`, and `CppIOStream` pass the native callback's buffer
directly to the stream's read/write operation. There is no intermediate C++
payload vector. Custom `std::streambuf` implementations receive those same
pointers in `xsgetn`/`xsputn`; any buffering performed inside a streambuf is
outside this adapter guarantee. The caller's streams must outlive the native
operation, and callback buffers must not be retained.

An HTTP resolver response body must still be allocated with `malloc`.
The native library reads directly from it without an intermediate body copy,
then calls `free` when the response is dropped, including error paths. After
returning the response, the resolver must not reuse or release its body.

## Read and validate an istream

Use the `Reader` constructor to read C2PA data from a stream. This constructor examines the specified stream for C2PA data in the given format, and its return value is a `Reader` that you can use to extract more information. The constructor throws exceptions on errors.
Expand Down
Loading