Crate imageflow [] [src]

Purpose

This module contains the functions exported for use by other languages.

If you're writing bindings, you're in the right place. Don't use imageflow_core::ffi, that's not correct - those are unstable and will disappear as C is replaced with Rust.

Don't call functions against the same context from multiple threads. You can create contexts from as many threads as you like, but you are responsible for synchronizing API calls on a per-context basis if you want to use one context from multiple threads. No use case for multithreaded Context access has been presented, so it is out of scope for API design.

Memory Lifetimes

In order to prevent dangling pointers, we must be correct about memory lifetimes.

... when allocated by Imageflow, assume the lifetime of the context

In Imageflow, by default, all things created with a context will be destroyed when the context is destroyed. Don't try to access ANYTHING imageflow has provided after the context is gone.

This is very nice, as it means that a client's failure to clean up will have limited impact on the process as a whole - as long as the client at minimum calls flow_context_destroy at the end of all possible code paths.

However, waiting to free memory and run destructors until the context is destroyed is not ideal; it increases our peak memory usage/needs and may cause operations to fail that would otherwise succeed.

There are two ways to mitigate this.

  1. When creating an I/O object, request it be cleaned up when the first job it is assigned to is cleaned up (instead of the context).
  2. Manually invoke the corresponding destroy function when you're done with the thing.

Destroying things

... when allocated by the client, Imageflow only borrows it for the invocation

Imageflow assumes that, at minimum, all pointers that you provide to it will, at minimum, remain valid for the duration of the API call. We'll call this 'borrowing'. Imageflow is just borrowing it for a bit; not taking ownership of the thing.

This may seem obvious, but it is not, in fact, guaranteed by garbage-collected languages. They are often oblivious to pointers, and cannot track what data is and is not referenced. Therefore, we suggest that you ensure every allocation made (and handed to Imageflow) is referenced after the imageflow API call, preferably in a way that will not be optimized away at runtime. Many languages and FFI libraries offer a utility method just for this purpose.

... although Imageflow may borrow some strings for the life of the context, yet not own them.

This happens for strings that are usually static constants, and unlikely to be allocated on the heap anyway.

... and it should be very clear when Imageflow is taking ownership of something you created!

When Imageflow needs continued access to data that is NOT highly likely to be static, it will be documented.

What if I need something to outlive the context?

Copy it before the context is destroyed.

Data types

Reference for those creating bindings in other languages

Two types are platform-specific - use the corresponding pointer or size type that varies with your platform.

Treat *mut Context, *mut Job, *mut JobIo, *mut JsonResponse ALL as opaque pointers.

Strings

ASCII is a safe subset of UTF-8; therefore wherever Imageflow asks for UTF-8 encoded bytes, you may provide ASCII instead.

You will provide Imageflow with strings in one of 3 ways: * UTF-8 null-terminated. You'll see something like libc::char, but no length parameter. Short and likely static strings are usually transmitted this way. * Operating system null-terminated. Only applicable to imageflow_io_create_for_file. * UTF-8 buffer with length. You'll usually see *const u8 and a length parameter. This is common for buffers of UTF-8 encoded json.

filename: *const libc::c_char function_name: *const libc::c_char

Fixed size

Structs

Consider all structures to be opaque. Do not attempt to access fields by offsets; rather, use the accessor functions provided.

Failure behavior

If you provide a null pointer for imageflow_context, then the process should terminate. This "fail fast" behavior offers the best opportunity for a useful stacktrace, and it's not a recoverable error.

Macros

static_char

Creates a static, null-terminated Rust string, and returns a *const libc::c_char pointer to it.

Structs

Context
Job
JobIo
JsonResponse

ImaeflowJsonResponse contains a buffer and buffer length (in bytes), as well as a status code The status code can be used to avoid actual parsing of the response in some cases. For example, you may not care about parsing an error message if you're hacking around - Or, you may not care about success details if you were sending a command that doesn't imply a result.

Enums

CleanupWith

When a resource should be closed/freed/cleaned up

Direction

Input or output?

IoMode

What is possible with the IO object

Lifetime

How long the provided pointer/buffer will remain valid. Callers must prevent the memory from being freed or moved until this contract expires.

Functions

exercise_create_destroy
exercise_error_handling
exercise_json_message
imageflow_context_add_to_callstack

Adds the given filename, line number, and function name to the call stack. Strings function_name, and filename should be null-terminated UTF-8 strings who will outlive context

imageflow_context_begin_terminate

Begins the process of destroying the context, yet leaves error information intact so that any errors in the tear-down process can be debugged with imageflow_context_error_and_stacktrace.

imageflow_context_clear_error

Clear the error state. This assumes that you know which API call failed and the problem has been resolved. Don't use this unless you're sure you've accounted for all possible inconsistent state (and fully understand the code paths that led to the error).

imageflow_context_create

Creates and returns an imageflow context. An imageflow context is required for all other imageflow API calls.

imageflow_context_destroy

Destroys the imageflow context and frees the context object. Only use this with contexts created using imageflow_context_create

imageflow_context_error_and_stacktrace

Prints the error messages and stacktrace to the given buffer in UTF-8 form; writes a null character to terminate the string, and ALSO returns the number of bytes written.

imageflow_context_error_code

Returns the numeric code associated with the error.

imageflow_context_has_error

Returns true if the context is in an error state. You must immediately deal with the error, as subsequent API calls will fail or cause undefined behavior until the error state is cleared

imageflow_context_memory_allocate

Allocates zeroed memory that will be freed with the context.

imageflow_context_memory_free

Frees memory allocated with imageflow_context_memory_allocate early.

imageflow_context_print_and_exit_if_error

Prints the error to stderr and exits the process if an error has been raised on the context. If no error is present, the function returns false.

imageflow_context_raise_error

Raises an error on the context.

imageflow_context_send_json

Sends a JSON message to the imageflow_context

imageflow_io_create_for_file

Creates an imageflow_io object to wrap a filename.

imageflow_io_create_for_output_buffer

Creates an imageflow_io structure for writing to an expanding memory buffer.

imageflow_io_create_from_buffer

Creates an imageflow_io structure for reading from the provided buffer. You are ALWAYS responsible for freeing the memory provided in accordance with the Lifetime value. If you specify OutlivesFunctionCall, then the buffer will be copied.

imageflow_io_get_output_buffer

Provides access to the underlying buffer for the given imageflow_io object.

imageflow_job_add_io

Associates the imageflow_io object with the job and the assigned io_id.

imageflow_job_create

Creates an imageflow_job, which permits the association of imageflow_io instances with numeric identifiers and provides a 'sub-context' for job execution

imageflow_job_destroy

Destroys the provided imageflow_job

imageflow_job_get_io

Looks up the imageflow_io pointer from the provided io_id

imageflow_job_get_output_buffer_by_id

Provides access to the underlying buffer for the given imageflow_io object.

imageflow_job_send_json

Sends a JSON message to the imageflow_job

imageflow_json_response_destroy

Frees memory associated with the given object (and owned objects) after running any owned or attached destructors. Returns false if something went wrong during tear-down.

imageflow_json_response_read

Writes fields from the given imageflow_json_response to the locations referenced. The buffer pointer sent out will be a UTF-8 byte array of the given length (not null-terminated). It will also become invalid if the JsonResponse associated is freed, or if the context is destroyed.