Compare commits
2 Commits
b3eb569553
...
b1ccb71938
Author | SHA1 | Date |
---|---|---|
Francisco Gindre | b1ccb71938 | |
Francisco Gindre | 964a88229b |
41
src/lib.rs
41
src/lib.rs
|
@ -1,6 +1,7 @@
|
|||
|
||||
// mod zcash_address::{ZcashAddress};
|
||||
uniffi_macros::include_scaffolding!("zcash_address");
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use zcash_address::{ZcashAddress, ParseError};
|
||||
|
||||
|
@ -17,13 +18,22 @@ pub enum AddressError {
|
|||
#[derive(Debug)]
|
||||
pub struct Address {
|
||||
string: String,
|
||||
kind: AddressType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AddressType {
|
||||
Sprout,
|
||||
Transparent,
|
||||
Sapling,
|
||||
Unified,
|
||||
}
|
||||
|
||||
fn parse(
|
||||
address_text: String
|
||||
) -> Result<Address, AddressError> {
|
||||
ZcashAddress::try_from_encoded(&address_text.as_str())
|
||||
.map(|zcash_address| zcash_address.to_address())
|
||||
.map( |zcash_address| Address::try_from(&zcash_address).unwrap())
|
||||
.map_err(|e| e.to_address_error())
|
||||
}
|
||||
|
||||
|
@ -50,9 +60,6 @@ fn derive_unified_address(
|
|||
) -> Result<Address, AddressError> {
|
||||
Err(AddressError::InvalidAddress)
|
||||
}
|
||||
trait ToAddress {
|
||||
fn to_address(&self) -> Address;
|
||||
}
|
||||
|
||||
trait ToAddressError {
|
||||
fn to_address_error(&self) -> AddressError;
|
||||
|
@ -67,12 +74,24 @@ impl ToAddressError for ParseError {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl ToAddress for ZcashAddress {
|
||||
fn to_address(&self) -> Address {
|
||||
let address = Address {
|
||||
string: self.to_string()
|
||||
};
|
||||
return address
|
||||
|
||||
impl TryFrom<&ZcashAddress> for Address {
|
||||
type Error = AddressError;
|
||||
|
||||
fn try_from(zcash_address:&ZcashAddress) -> Result<Address, Self::Error> {
|
||||
let address_kind = AddressType::try_from(zcash_address).unwrap();
|
||||
let address = Address {
|
||||
string: zcash_address.to_string(),
|
||||
kind: address_kind,
|
||||
};
|
||||
return Ok(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&ZcashAddress> for AddressType {
|
||||
type Error = AddressError;
|
||||
|
||||
fn try_from(_: &ZcashAddress) -> Result<AddressType, Self::Error> {
|
||||
Ok(AddressType::Sapling)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,17 @@ namespace zcash_address_util {
|
|||
Address derive_unified_address([ByRef] sequence<u8> seed_bytes, i32 account, i32 index);
|
||||
};
|
||||
|
||||
|
||||
enum AddressType {
|
||||
"Sprout",
|
||||
"Transparent",
|
||||
"Sapling",
|
||||
"Unified"
|
||||
};
|
||||
|
||||
dictionary Address {
|
||||
string string;
|
||||
AddressType kind;
|
||||
};
|
||||
|
||||
[Error]
|
||||
|
|
|
@ -0,0 +1,530 @@
|
|||
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
|
||||
import Foundation
|
||||
|
||||
// Depending on the consumer's build setup, the low-level FFI code
|
||||
// might be in a separate module, or it might be compiled inline into
|
||||
// this module. This is a bit of light hackery to work with both.
|
||||
#if canImport(zcash_address_utilFFI)
|
||||
import zcash_address_utilFFI
|
||||
#endif
|
||||
|
||||
private extension RustBuffer {
|
||||
// Allocate a new buffer, copying the contents of a `UInt8` array.
|
||||
init(bytes: [UInt8]) {
|
||||
let rbuf = bytes.withUnsafeBufferPointer { ptr in
|
||||
try! rustCall { ffi_zcash_address_util_66b8_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) }
|
||||
}
|
||||
self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data)
|
||||
}
|
||||
|
||||
// Frees the buffer in place.
|
||||
// The buffer must not be used after this is called.
|
||||
func deallocate() {
|
||||
try! rustCall { ffi_zcash_address_util_66b8_rustbuffer_free(self, $0) }
|
||||
}
|
||||
}
|
||||
|
||||
private extension ForeignBytes {
|
||||
init(bufferPointer: UnsafeBufferPointer<UInt8>) {
|
||||
self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress)
|
||||
}
|
||||
}
|
||||
|
||||
// For every type used in the interface, we provide helper methods for conveniently
|
||||
// lifting and lowering that type from C-compatible data, and for reading and writing
|
||||
// values of that type in a buffer.
|
||||
|
||||
// Helper classes/extensions that don't change.
|
||||
// Someday, this will be in a libray of its own.
|
||||
|
||||
private extension Data {
|
||||
init(rustBuffer: RustBuffer) {
|
||||
// TODO: This copies the buffer. Can we read directly from a
|
||||
// Rust buffer?
|
||||
self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len))
|
||||
}
|
||||
}
|
||||
|
||||
// A helper class to read values out of a byte buffer.
|
||||
private class Reader {
|
||||
let data: Data
|
||||
var offset: Data.Index
|
||||
|
||||
init(data: Data) {
|
||||
self.data = data
|
||||
offset = 0
|
||||
}
|
||||
|
||||
// Reads an integer at the current offset, in big-endian order, and advances
|
||||
// the offset on success. Throws if reading the integer would move the
|
||||
// offset past the end of the buffer.
|
||||
func readInt<T: FixedWidthInteger>() throws -> T {
|
||||
let range = offset ..< offset + MemoryLayout<T>.size
|
||||
guard data.count >= range.upperBound else {
|
||||
throw UniffiInternalError.bufferOverflow
|
||||
}
|
||||
if T.self == UInt8.self {
|
||||
let value = data[offset]
|
||||
offset += 1
|
||||
return value as! T
|
||||
}
|
||||
var value: T = 0
|
||||
_ = withUnsafeMutableBytes(of: &value) { data.copyBytes(to: $0, from: range) }
|
||||
offset = range.upperBound
|
||||
return value.bigEndian
|
||||
}
|
||||
|
||||
// Reads an arbitrary number of bytes, to be used to read
|
||||
// raw bytes, this is useful when lifting strings
|
||||
func readBytes(count: Int) throws -> [UInt8] {
|
||||
let range = offset ..< (offset + count)
|
||||
guard data.count >= range.upperBound else {
|
||||
throw UniffiInternalError.bufferOverflow
|
||||
}
|
||||
var value = [UInt8](repeating: 0, count: count)
|
||||
value.withUnsafeMutableBufferPointer { buffer in
|
||||
data.copyBytes(to: buffer, from: range)
|
||||
}
|
||||
offset = range.upperBound
|
||||
return value
|
||||
}
|
||||
|
||||
// Reads a float at the current offset.
|
||||
@inlinable
|
||||
func readFloat() throws -> Float {
|
||||
return Float(bitPattern: try readInt())
|
||||
}
|
||||
|
||||
// Reads a float at the current offset.
|
||||
@inlinable
|
||||
func readDouble() throws -> Double {
|
||||
return Double(bitPattern: try readInt())
|
||||
}
|
||||
|
||||
// Indicates if the offset has reached the end of the buffer.
|
||||
@inlinable
|
||||
func hasRemaining() -> Bool {
|
||||
return offset < data.count
|
||||
}
|
||||
}
|
||||
|
||||
// A helper class to write values into a byte buffer.
|
||||
private class Writer {
|
||||
var bytes: [UInt8]
|
||||
var offset: Array<UInt8>.Index
|
||||
|
||||
init() {
|
||||
bytes = []
|
||||
offset = 0
|
||||
}
|
||||
|
||||
func writeBytes<S>(_ byteArr: S) where S: Sequence, S.Element == UInt8 {
|
||||
bytes.append(contentsOf: byteArr)
|
||||
}
|
||||
|
||||
// Writes an integer in big-endian order.
|
||||
//
|
||||
// Warning: make sure what you are trying to write
|
||||
// is in the correct type!
|
||||
func writeInt<T: FixedWidthInteger>(_ value: T) {
|
||||
var value = value.bigEndian
|
||||
withUnsafeBytes(of: &value) { bytes.append(contentsOf: $0) }
|
||||
}
|
||||
|
||||
@inlinable
|
||||
func writeFloat(_ value: Float) {
|
||||
writeInt(value.bitPattern)
|
||||
}
|
||||
|
||||
@inlinable
|
||||
func writeDouble(_ value: Double) {
|
||||
writeInt(value.bitPattern)
|
||||
}
|
||||
}
|
||||
|
||||
// Types conforming to `Serializable` can be read and written in a bytebuffer.
|
||||
private protocol Serializable {
|
||||
func write(into: Writer)
|
||||
static func read(from: Reader) throws -> Self
|
||||
}
|
||||
|
||||
// Types confirming to `ViaFfi` can be transferred back-and-for over the FFI.
|
||||
// This is analogous to the Rust trait of the same name.
|
||||
private protocol ViaFfi: Serializable {
|
||||
associatedtype FfiType
|
||||
static func lift(_ v: FfiType) throws -> Self
|
||||
func lower() -> FfiType
|
||||
}
|
||||
|
||||
// Types conforming to `Primitive` pass themselves directly over the FFI.
|
||||
private protocol Primitive {}
|
||||
|
||||
private extension Primitive {
|
||||
typealias FfiType = Self
|
||||
|
||||
static func lift(_ v: Self) throws -> Self {
|
||||
return v
|
||||
}
|
||||
|
||||
func lower() -> Self {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// Types conforming to `ViaFfiUsingByteBuffer` lift and lower into a bytebuffer.
|
||||
// Use this for complex types where it's hard to write a custom lift/lower.
|
||||
private protocol ViaFfiUsingByteBuffer: Serializable {}
|
||||
|
||||
private extension ViaFfiUsingByteBuffer {
|
||||
typealias FfiType = RustBuffer
|
||||
|
||||
static func lift(_ buf: RustBuffer) throws -> Self {
|
||||
let reader = Reader(data: Data(rustBuffer: buf))
|
||||
let value = try Self.read(from: reader)
|
||||
if reader.hasRemaining() {
|
||||
throw UniffiInternalError.incompleteData
|
||||
}
|
||||
buf.deallocate()
|
||||
return value
|
||||
}
|
||||
|
||||
func lower() -> RustBuffer {
|
||||
let writer = Writer()
|
||||
write(into: writer)
|
||||
return RustBuffer(bytes: writer.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Implement our protocols for the built-in types that we use.
|
||||
|
||||
extension Array: ViaFfiUsingByteBuffer, ViaFfi, Serializable where Element: Serializable {
|
||||
fileprivate static func read(from buf: Reader) throws -> Self {
|
||||
let len: Int32 = try buf.readInt()
|
||||
var seq = [Element]()
|
||||
seq.reserveCapacity(Int(len))
|
||||
for _ in 0 ..< len {
|
||||
seq.append(try Element.read(from: buf))
|
||||
}
|
||||
return seq
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
let len = Int32(count)
|
||||
buf.writeInt(len)
|
||||
for item in self {
|
||||
item.write(into: buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt8: Primitive, ViaFfi {
|
||||
fileprivate static func read(from buf: Reader) throws -> UInt8 {
|
||||
return try lift(buf.readInt())
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
buf.writeInt(lower())
|
||||
}
|
||||
}
|
||||
|
||||
extension Int32: Primitive, ViaFfi {
|
||||
fileprivate static func read(from buf: Reader) throws -> Int32 {
|
||||
return try lift(buf.readInt())
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
buf.writeInt(lower())
|
||||
}
|
||||
}
|
||||
|
||||
extension String: ViaFfi {
|
||||
fileprivate typealias FfiType = RustBuffer
|
||||
|
||||
fileprivate static func lift(_ v: FfiType) throws -> Self {
|
||||
defer {
|
||||
try! rustCall { ffi_zcash_address_util_66b8_rustbuffer_free(v, $0) }
|
||||
}
|
||||
if v.data == nil {
|
||||
return String()
|
||||
}
|
||||
let bytes = UnsafeBufferPointer<UInt8>(start: v.data!, count: Int(v.len))
|
||||
return String(bytes: bytes, encoding: String.Encoding.utf8)!
|
||||
}
|
||||
|
||||
fileprivate func lower() -> FfiType {
|
||||
return utf8CString.withUnsafeBufferPointer { ptr in
|
||||
// The swift string gives us int8_t, we want uint8_t.
|
||||
ptr.withMemoryRebound(to: UInt8.self) { ptr in
|
||||
// The swift string gives us a trailing null byte, we don't want it.
|
||||
let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1))
|
||||
let bytes = ForeignBytes(bufferPointer: buf)
|
||||
return try! rustCall { ffi_zcash_address_util_66b8_rustbuffer_from_bytes(bytes, $0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate static func read(from buf: Reader) throws -> Self {
|
||||
let len: Int32 = try buf.readInt()
|
||||
return String(bytes: try buf.readBytes(count: Int(len)), encoding: String.Encoding.utf8)!
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
let len = Int32(utf8.count)
|
||||
buf.writeInt(len)
|
||||
buf.writeBytes(utf8)
|
||||
}
|
||||
}
|
||||
|
||||
// Public interface members begin here.
|
||||
|
||||
// Note that we don't yet support `indirect` for enums.
|
||||
// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
|
||||
public enum AddressType {
|
||||
case sprout
|
||||
case transparent
|
||||
case sapling
|
||||
case unified
|
||||
}
|
||||
|
||||
extension AddressType: ViaFfiUsingByteBuffer, ViaFfi {
|
||||
fileprivate static func read(from buf: Reader) throws -> AddressType {
|
||||
let variant: Int32 = try buf.readInt()
|
||||
switch variant {
|
||||
case 1: return .sprout
|
||||
case 2: return .transparent
|
||||
case 3: return .sapling
|
||||
case 4: return .unified
|
||||
default: throw UniffiInternalError.unexpectedEnumCase
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
switch self {
|
||||
case .sprout:
|
||||
buf.writeInt(Int32(1))
|
||||
|
||||
case .transparent:
|
||||
buf.writeInt(Int32(2))
|
||||
|
||||
case .sapling:
|
||||
buf.writeInt(Int32(3))
|
||||
|
||||
case .unified:
|
||||
buf.writeInt(Int32(4))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressType: Equatable, Hashable {}
|
||||
// An error type for FFI errors. These errors occur at the UniFFI level, not
|
||||
// the library level.
|
||||
private enum UniffiInternalError: LocalizedError {
|
||||
case bufferOverflow
|
||||
case incompleteData
|
||||
case unexpectedOptionalTag
|
||||
case unexpectedEnumCase
|
||||
case unexpectedNullPointer
|
||||
case unexpectedRustCallStatusCode
|
||||
case unexpectedRustCallError
|
||||
case rustPanic(_ message: String)
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .bufferOverflow: return "Reading the requested value would read past the end of the buffer"
|
||||
case .incompleteData: return "The buffer still has data after lifting its containing value"
|
||||
case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1"
|
||||
case .unexpectedEnumCase: return "Raw enum value doesn't match any cases"
|
||||
case .unexpectedNullPointer: return "Raw pointer value was null"
|
||||
case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code"
|
||||
case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified"
|
||||
case let .rustPanic(message): return message
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let CALL_SUCCESS: Int8 = 0
|
||||
private let CALL_ERROR: Int8 = 1
|
||||
private let CALL_PANIC: Int8 = 2
|
||||
|
||||
private extension RustCallStatus {
|
||||
init() {
|
||||
self.init(
|
||||
code: CALL_SUCCESS,
|
||||
errorBuf: RustBuffer(
|
||||
capacity: 0,
|
||||
len: 0,
|
||||
data: nil
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public enum AddressError {
|
||||
// Simple error enums only carry a message
|
||||
case InvalidAddress(message: String)
|
||||
|
||||
// Simple error enums only carry a message
|
||||
case NotZcash(message: String)
|
||||
|
||||
// Simple error enums only carry a message
|
||||
case InvalidUnifiedAddress(message: String)
|
||||
}
|
||||
|
||||
extension AddressError: ViaFfiUsingByteBuffer, ViaFfi {
|
||||
fileprivate static func read(from buf: Reader) throws -> AddressError {
|
||||
let variant: Int32 = try buf.readInt()
|
||||
switch variant {
|
||||
case 1: return .InvalidAddress(
|
||||
message: try String.read(from: buf)
|
||||
)
|
||||
|
||||
case 2: return .NotZcash(
|
||||
message: try String.read(from: buf)
|
||||
)
|
||||
|
||||
case 3: return .InvalidUnifiedAddress(
|
||||
message: try String.read(from: buf)
|
||||
)
|
||||
|
||||
default: throw UniffiInternalError.unexpectedEnumCase
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func write(into buf: Writer) {
|
||||
switch self {
|
||||
case let .InvalidAddress(message):
|
||||
buf.writeInt(Int32(1))
|
||||
message.write(into: buf)
|
||||
case let .NotZcash(message):
|
||||
buf.writeInt(Int32(2))
|
||||
message.write(into: buf)
|
||||
case let .InvalidUnifiedAddress(message):
|
||||
buf.writeInt(Int32(3))
|
||||
message.write(into: buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressError: Equatable, Hashable {}
|
||||
|
||||
extension AddressError: Error {}
|
||||
|
||||
private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||
try makeRustCall(callback, errorHandler: {
|
||||
$0.deallocate()
|
||||
return UniffiInternalError.unexpectedRustCallError
|
||||
})
|
||||
}
|
||||
|
||||
private func rustCallWithError<T, E: ViaFfiUsingByteBuffer & Error>(_: E.Type, _ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||
try makeRustCall(callback, errorHandler: { try E.lift($0) })
|
||||
}
|
||||
|
||||
private func makeRustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T, errorHandler: (RustBuffer) throws -> Error) throws -> T {
|
||||
var callStatus = RustCallStatus()
|
||||
let returnedVal = callback(&callStatus)
|
||||
switch callStatus.code {
|
||||
case CALL_SUCCESS:
|
||||
return returnedVal
|
||||
|
||||
case CALL_ERROR:
|
||||
throw try errorHandler(callStatus.errorBuf)
|
||||
|
||||
case CALL_PANIC:
|
||||
// When the rust code sees a panic, it tries to construct a RustBuffer
|
||||
// with the message. But if that code panics, then it just sends back
|
||||
// an empty buffer.
|
||||
if callStatus.errorBuf.len > 0 {
|
||||
throw UniffiInternalError.rustPanic(try String.lift(callStatus.errorBuf))
|
||||
} else {
|
||||
callStatus.errorBuf.deallocate()
|
||||
throw UniffiInternalError.rustPanic("Rust panic")
|
||||
}
|
||||
|
||||
default:
|
||||
throw UniffiInternalError.unexpectedRustCallStatusCode
|
||||
}
|
||||
}
|
||||
|
||||
public struct Address {
|
||||
public var string: String
|
||||
public var kind: AddressType
|
||||
|
||||
// Default memberwise initializers are never public by default, so we
|
||||
// declare one manually.
|
||||
public init(string: String, kind: AddressType) {
|
||||
self.string = string
|
||||
self.kind = kind
|
||||
}
|
||||
}
|
||||
|
||||
extension Address: Equatable, Hashable {
|
||||
public static func == (lhs: Address, rhs: Address) -> Bool {
|
||||
if lhs.string != rhs.string {
|
||||
return false
|
||||
}
|
||||
if lhs.kind != rhs.kind {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(string)
|
||||
hasher.combine(kind)
|
||||
}
|
||||
}
|
||||
|
||||
private extension Address {
|
||||
static func read(from buf: Reader) throws -> Address {
|
||||
return try Address(
|
||||
string: String.read(from: buf),
|
||||
kind: AddressType.read(from: buf)
|
||||
)
|
||||
}
|
||||
|
||||
func write(into buf: Writer) {
|
||||
string.write(into: buf)
|
||||
kind.write(into: buf)
|
||||
}
|
||||
}
|
||||
|
||||
extension Address: ViaFfiUsingByteBuffer, ViaFfi {}
|
||||
|
||||
public func parse(addressText: String) throws -> Address {
|
||||
let _retval = try
|
||||
|
||||
rustCallWithError(AddressError.self) {
|
||||
zcash_address_util_66b8_parse(addressText.lower(), $0)
|
||||
}
|
||||
return try Address.lift(_retval)
|
||||
}
|
||||
|
||||
public func deriveTransparentAddress(seedBytes: [UInt8], account: Int32, index: Int32) throws -> Address {
|
||||
let _retval = try
|
||||
|
||||
rustCallWithError(AddressError.self) {
|
||||
zcash_address_util_66b8_derive_transparent_address(seedBytes.lower(), account.lower(), index.lower(), $0)
|
||||
}
|
||||
return try Address.lift(_retval)
|
||||
}
|
||||
|
||||
public func deriveSaplingAddress(seedBytes: [UInt8], account: Int32, index: Int32) throws -> Address {
|
||||
let _retval = try
|
||||
|
||||
rustCallWithError(AddressError.self) {
|
||||
zcash_address_util_66b8_derive_sapling_address(seedBytes.lower(), account.lower(), index.lower(), $0)
|
||||
}
|
||||
return try Address.lift(_retval)
|
||||
}
|
||||
|
||||
public func deriveUnifiedAddress(seedBytes: [UInt8], account: Int32, index: Int32) throws -> Address {
|
||||
let _retval = try
|
||||
|
||||
rustCallWithError(AddressError.self) {
|
||||
zcash_address_util_66b8_derive_unified_address(seedBytes.lower(), account.lower(), index.lower(), $0)
|
||||
}
|
||||
return try Address.lift(_retval)
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// The following structs are used to implement the lowest level
|
||||
// of the FFI, and thus useful to multiple uniffied crates.
|
||||
// We ensure they are declared exactly once, with a header guard, UNIFFI_SHARED_H.
|
||||
#ifdef UNIFFI_SHARED_H
|
||||
// We also try to prevent mixing versions of shared uniffi header structs.
|
||||
// If you add anything to the #else block, you must increment the version suffix in UNIFFI_SHARED_HEADER_V3
|
||||
#ifndef UNIFFI_SHARED_HEADER_V3
|
||||
#error Combining helper code from multiple versions of uniffi is not supported
|
||||
#endif // ndef UNIFFI_SHARED_HEADER_V3
|
||||
#else
|
||||
#define UNIFFI_SHARED_H
|
||||
#define UNIFFI_SHARED_HEADER_V3
|
||||
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V3 in this file. ⚠️
|
||||
|
||||
typedef struct RustBuffer
|
||||
{
|
||||
int32_t capacity;
|
||||
int32_t len;
|
||||
uint8_t *_Nullable data;
|
||||
} RustBuffer;
|
||||
|
||||
typedef struct ForeignBytes
|
||||
{
|
||||
int32_t len;
|
||||
const uint8_t *_Nullable data;
|
||||
} ForeignBytes;
|
||||
|
||||
// Error definitions
|
||||
typedef struct RustCallStatus {
|
||||
int8_t code;
|
||||
RustBuffer errorBuf;
|
||||
} RustCallStatus;
|
||||
|
||||
// ⚠️ Attention: If you change this #else block (ending in `#endif // def UNIFFI_SHARED_H`) you *must* ⚠️
|
||||
// ⚠️ increment the version suffix in all instances of UNIFFI_SHARED_HEADER_V3 in this file. ⚠️
|
||||
#endif // def UNIFFI_SHARED_H
|
||||
|
||||
RustBuffer zcash_address_util_66b8_parse(
|
||||
RustBuffer address_text,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer zcash_address_util_66b8_derive_transparent_address(
|
||||
RustBuffer seed_bytes,int32_t account,int32_t index,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer zcash_address_util_66b8_derive_sapling_address(
|
||||
RustBuffer seed_bytes,int32_t account,int32_t index,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer zcash_address_util_66b8_derive_unified_address(
|
||||
RustBuffer seed_bytes,int32_t account,int32_t index,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer ffi_zcash_address_util_66b8_rustbuffer_alloc(
|
||||
int32_t size,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer ffi_zcash_address_util_66b8_rustbuffer_from_bytes(
|
||||
ForeignBytes bytes,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
void ffi_zcash_address_util_66b8_rustbuffer_free(
|
||||
RustBuffer buf,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
||||
RustBuffer ffi_zcash_address_util_66b8_rustbuffer_reserve(
|
||||
RustBuffer buf,int32_t additional,
|
||||
RustCallStatus *_Nonnull out_status
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
// This file was autogenerated by some hot garbage in the `uniffi` crate.
|
||||
// Trust me, you don't want to mess with it!
|
||||
module zcash_address_utilFFI {
|
||||
header "zcash_address_utilFFI.h"
|
||||
export *
|
||||
}
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
// do {
|
||||
// let testSaplingAddress = "ztestsapling1ysrf4uq52n5hhj0vzxpcfneszlk8flalh3ajdwsyucnpc0fjktp9afzcclnxdrnzfl7w7wyx3kz"
|
||||
// // let parsedAddress = try zcash_address.parse(testSaplingAddress)
|
||||
// // assert(parsedAddress.network == .test)
|
||||
// assert(true)
|
||||
// let parsedAddress = try zcash_address.parse(testSaplingAddress)
|
||||
// // assert(parsedAddress.kind == .sapling)
|
||||
// // assert(parsedAddress.string == testSaplingAddress)
|
||||
// } catch {
|
||||
// fatalError("Invalid Address when it should have been valid")
|
||||
// }
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[bindings.swift]
|
||||
cdylib_name = "zcash_address_util"
|
Loading…
Reference in New Issue