Use protobuf for fxa_profile return value

This commit is contained in:
Edouard Oger 2019-02-05 16:44:51 -05:00
Родитель 1f4b407288
Коммит 365390dfee
27 изменённых файлов: 549 добавлений и 114 удалений

7
.gitignore поставляемый
Просмотреть файл

@ -17,3 +17,10 @@ captures
# iOS stuff.
xcuserdata
# Protobuf Swift
*.pb.swift
# Carthage built artifacts
Cartfile.resolved
Carthage

Просмотреть файл

@ -5,6 +5,8 @@ before_deploy:
- rustup target add aarch64-apple-ios armv7-apple-ios i386-apple-ios x86_64-apple-ios
- cargo install cargo-lipo
- brew update && (brew outdated carthage || brew upgrade carthage)
- brew install swift-protobuf
- carthage bootstrap
- carthage build --no-skip-current --verbose
- carthage archive --output $FRAMEWORK_NAME
- rm -rf Carthage

Просмотреть файл

@ -4,6 +4,19 @@
[Full Changelog](https://github.com/mozilla/application-services/compare/v0.16.1...master)
## FxA
### What's New
- We are now using [Protocol Buffers](https://developers.google.com/protocol-buffers/) to pass the Profile data across the FFI boundaries, both on Android and iOS. On Android there should be no breaking changes.
### Breaking changes
- iOS: You now have to include the `SwiftProtobuf` framework in your projects for FxAClient to work (otherwise you'll get a runtime error when fetching the user profile). It is built into `Carthage/Build/iOS` just like `FxAClient.framework`.
- iOS: In order to build FxAClient from source, you need [swift-protobuf](https://github.com/apple/swift-protobuf) installed. Simply run `brew install swift-protobuf` if you have Homebrew.
- iOS: You need to run `carthage bootstrap` at the root of the repository at least once before building the FxAClient project: this will build the `SwiftProtobuf.framework` file needed by the project.
- iOS: the `Profile` class now inherits from `RustProtobuf`. Nothing should change in practice for you.
# 0.16.1 (_2019-02-08_)
[Full Changelog](https://github.com/mozilla/application-services/compare/v0.16.0...v0.16.1)

125
Cargo.lock сгенерированный
Просмотреть файл

@ -484,13 +484,14 @@ dependencies = [
[[package]]
name = "ffi-support"
version = "0.1.5"
version = "0.1.6"
dependencies = [
"backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"prost 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -505,6 +506,11 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fixedbitset"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fnv"
version = "1.0.6"
@ -562,13 +568,17 @@ version = "0.1.0"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"hawk 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)",
"prost 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prost-build 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prost-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -585,7 +595,7 @@ name = "fxaclient_ffi"
version = "0.1.0"
dependencies = [
"android_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"fxa-client 0.1.0",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -732,6 +742,14 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.8.0"
@ -832,7 +850,7 @@ dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"fxa-client 0.1.0",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -854,7 +872,7 @@ version = "0.1.0"
dependencies = [
"android_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"base16 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"logins 0.1.0",
@ -952,6 +970,11 @@ name = "more-asserts"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "multimap"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "native-tls"
version = "0.2.2"
@ -1068,6 +1091,14 @@ name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "petgraph"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "phf"
version = "0.7.24"
@ -1118,7 +1149,7 @@ dependencies = [
"criterion 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"find-places-db 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fxa-client 0.1.0",
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1148,7 +1179,7 @@ name = "places-ffi"
version = "0.1.0"
dependencies = [
"android_logger 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"places 0.1.0",
@ -1192,6 +1223,55 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prost"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prost-build"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)",
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"prost 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prost-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prost-derive"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prost-types"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"prost 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prost-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quick-error"
version = "1.2.2"
@ -1368,7 +1448,7 @@ dependencies = [
name = "rc_log_ffi"
version = "0.1.0"
dependencies = [
"ffi-support 0.1.5",
"ffi-support 0.1.6",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1692,6 +1772,16 @@ dependencies = [
"syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.26"
@ -2099,6 +2189,15 @@ name = "webbrowser"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "which"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
@ -2210,6 +2309,7 @@ dependencies = [
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum find-places-db 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "156072cf5b7e3974da51941bf050f5b8ab5a8df56ad5c1adbd8c07e9d9455b95"
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
@ -2231,6 +2331,7 @@ dependencies = [
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum itertools 0.7.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@ -2253,6 +2354,7 @@ dependencies = [
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum more-asserts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
"checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151"
"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
@ -2266,6 +2368,7 @@ dependencies = [
"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
@ -2274,6 +2377,10 @@ dependencies = [
"checksum prettytable-rs 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "34dc1f4f6dddab3bf008ecfd4fd2a631b585fbf0af123f34c1324f51a034ff5f"
"checksum prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5511ca4c805aa35f0abff6be7923231d664408b60c09f44ef715f2bce106cd9e"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
"checksum prost 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f36c478cd43382388dfc3a3679af175c03d19ed8039e79a3e4447e944cd3f3"
"checksum prost-build 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6325275b85605f58f576456a47af44417edf5956a6f670bb59fbe12aff69597"
"checksum prost-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9787d1977ea72e8066d58e46ae66100324a2815e677897fe78dfe54958f48252"
"checksum prost-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5644c57d56bc085f9570e113495c1f08d7185beca700dcc296cb4672f380a679"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
@ -2329,6 +2436,7 @@ dependencies = [
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum structopt 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "670ad348dc73012fcf78c71f06f9d942232cdd4c859d4b6975e27836c3efc0c3"
"checksum structopt-derive 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ef98172b1a00b0bec738508d3726540edcbd186d50dfd326f2b1febbb3559f04"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
@ -2372,6 +2480,7 @@ dependencies = [
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3"
"checksum webbrowser 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "21c311234fd1392a0071c1476cb7a4338dd2479e03e80e2328fbbf2db117b028"
"checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

1
Cartfile Normal file
Просмотреть файл

@ -0,0 +1 @@
github "apple/swift-protobuf" ~> 1.0

Просмотреть файл

@ -37,6 +37,8 @@ buildscript {
// Downloading libs/ archives from Taskcluster.
classpath 'de.undercouch:gradle-download-task:3.4.3'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.8'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

Просмотреть файл

@ -7,12 +7,15 @@ authors = ["Edouard Oger <eoger@fastmail.com>"]
[dependencies]
base64 = "0.9.3"
byteorder = "1.2.6"
bytes = "0.4"
failure = "0.1.3"
hawk = { version = "1.0.5", optional = true }
hex = "0.3.2"
lazy_static = "1.0.0"
log = "0.4"
openssl = { version = "0.10.12", optional = true }
prost = "0.4"
prost-derive = "0.4"
regex = "1.0.0"
reqwest = "0.9.7"
ring = "0.14.5"
@ -26,6 +29,9 @@ ffi-support = { path = "../support/ffi", optional = true }
[dev-dependencies]
text_io = "0.1.7"
[build-dependencies]
prost-build = "0.4"
[features]
browserid = ["openssl", "hawk"]
ffi = ["ffi-support"]

Просмотреть файл

@ -2,6 +2,7 @@ apply plugin: 'com.android.library'
apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.protobuf'
android {
compileSdkVersion 27
@ -31,6 +32,14 @@ android {
packagingOptions {
doNotStrip "**/*.so"
}
sourceSets {
main {
proto {
srcDir '../src'
}
}
}
}
configurations {
@ -71,9 +80,31 @@ cargo {
exec = rootProject.ext.cargoExec
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.0.0'
}
plugins {
javalite {
artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
remove java
}
task.plugins {
javalite { }
}
}
}
}
dependencies {
implementation 'net.java.dev.jna:jna:4.5.2@aar'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.protobuf:protobuf-lite:3.0.0'
}
afterEvaluate {

Просмотреть файл

@ -0,0 +1,31 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fxaclient.internal
import com.google.protobuf.CodedInputStream
import com.sun.jna.Pointer
import com.sun.jna.Structure
import java.util.*
internal open class ByteBuffer : Structure() {
@JvmField var len: Long = 0
@JvmField var data: Pointer? = null
init {
read()
}
override fun getFieldOrder(): List<String> {
return Arrays.asList("len", "data")
}
fun asCodedInputStream(): CodedInputStream? {
return this.data?.let {
CodedInputStream.newInstance(it.getByteBuffer(0, this.len))
}
}
class ByValue : ByteBuffer(), Structure.ByValue
}

Просмотреть файл

@ -72,7 +72,7 @@ internal interface FxaClient : Library {
e: Error.ByReference
): Pointer?
fun fxa_profile(fxa: FxaHandle, ignoreCache: Boolean, e: Error.ByReference): Profile.Raw?
fun fxa_profile(fxa: FxaHandle, ignoreCache: Boolean, e: Error.ByReference): ByteBuffer.ByValue
fun fxa_get_token_server_endpoint_url(fxa: FxaHandle, e: Error.ByReference): Pointer?
fun fxa_get_connection_success_url(fxa: FxaHandle, e: Error.ByReference): Pointer?
@ -89,7 +89,7 @@ internal interface FxaClient : Library {
// when using Structure.
fun fxa_oauth_info_free(ptr: Pointer)
fun fxa_profile_free(ptr: Pointer)
fun fxa_bytebuffer_free(buffer: ByteBuffer.ByValue)
}
internal typealias FxaHandle = Long

Просмотреть файл

@ -4,12 +4,9 @@
package org.mozilla.fxaclient.internal
import com.sun.jna.Pointer
import com.sun.jna.Structure
import ffi_types.FfiTypes.Profile as RawProfile
import java.util.Arrays
class Profile internal constructor(raw: Raw) {
class Profile internal constructor(byteBuffer: ByteBuffer.ByValue) {
val uid: String?
val email: String?
@ -17,31 +14,22 @@ class Profile internal constructor(raw: Raw) {
val avatarDefault: Boolean
val displayName: String?
internal class Raw(p: Pointer) : Structure(p) {
@JvmField var uid: Pointer? = null
@JvmField var email: Pointer? = null
@JvmField var avatar: Pointer? = null
@JvmField var avatarDefault: Byte = 0
@JvmField var displayName: Pointer? = null
init {
read()
}
override fun getFieldOrder(): List<String> {
return Arrays.asList("uid", "email", "avatar", "avatarDefault", "displayName")
}
}
init {
try {
this.uid = raw.uid?.getRustString()
this.email = raw.email?.getRustString()
this.avatar = raw.avatar?.getRustString()
this.avatarDefault = raw.avatarDefault == 1.toByte()
this.displayName = raw.displayName?.getRustString()
val raw = byteBuffer.asCodedInputStream()?.let {
RawProfile.parseFrom(it)
} ?: run {
// TODO: should throw somehow?
RawProfile.getDefaultInstance()
}
this.uid = if (raw.hasUid()) raw.uid else null
this.email = if (raw.hasEmail()) raw.email else null
this.avatar = if (raw.hasAvatar()) raw.avatar else null
this.avatarDefault = raw.avatarDefault
this.displayName = if (raw.hasDisplayName()) raw.displayName else null
} finally {
FxaClient.INSTANCE.fxa_profile_free(raw.pointer)
FxaClient.INSTANCE.fxa_bytebuffer_free(byteBuffer)
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
fn main() {
prost_build::compile_protos(&["src/ffi_types.proto"], &["src/"]).unwrap();
}

Просмотреть файл

@ -9,7 +9,7 @@ name = "fxaclient_ffi"
crate-type = ["lib", "staticlib", "cdylib"]
[dependencies]
ffi-support = { path = "../../support/ffi" }
ffi-support = { path = "../../support/ffi", features = ["prost_support"] }
log = "0.4.6"
lazy_static = "1.2.0"

Просмотреть файл

@ -3,10 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use ffi_support::{
define_box_destructor, define_handle_map_deleter, define_string_destructor, rust_str_from_c,
ConcurrentHandleMap, ExternError,
define_box_destructor, define_bytebuffer_destructor, define_handle_map_deleter,
define_string_destructor, rust_str_from_c, ByteBuffer, ConcurrentHandleMap, ExternError,
};
use fxa_client::{ffi::*, FirefoxAccount, PersistCallback};
use fxa_client::{ffi::*, ffi_types, FirefoxAccount, PersistCallback};
use std::{ffi::CString, os::raw::c_char};
#[no_mangle]
@ -147,9 +147,12 @@ pub extern "C" fn fxa_profile(
handle: u64,
ignore_cache: bool,
error: &mut ExternError,
) -> *mut ProfileC {
) -> ByteBuffer {
log::debug!("fxa_profile");
ACCOUNTS.call_with_result_mut(error, handle, |fxa| fxa.get_profile(ignore_cache))
ACCOUNTS.call_with_result_mut(error, handle, |fxa| {
fxa.get_profile(ignore_cache)
.map(|p| Into::<ffi_types::Profile>::into(p))
})
}
/// Get the Sync token server endpoint URL.
@ -325,6 +328,6 @@ define_string_destructor!(fxa_str_free);
define_handle_map_deleter!(ACCOUNTS, fxa_free);
define_box_destructor!(AccessTokenInfoC, fxa_oauth_info_free);
define_box_destructor!(ProfileC, fxa_profile_free);
#[cfg(feature = "browserid")]
define_box_destructor!(SyncKeysC, fxa_sync_keys_free);
define_bytebuffer_destructor!(fxa_bytebuffer_free);

Просмотреть файл

@ -7,10 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
CE2F4D42220E0014001ECF92 /* ffi_types.proto in Sources */ = {isa = PBXBuildFile; fileRef = CE2F4D41220E0014001ECF92 /* ffi_types.proto */; };
CE3E9D3520A36B63001B4B14 /* libfxaclient_ffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE7B4B8A20A36B0500FC4422 /* libfxaclient_ffi.a */; };
CE9D202520914D0D00F1C8FA /* FxAClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CE9D202320914D0D00F1C8FA /* FxAClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE9D203120914D2600F1C8FA /* FirefoxAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9D202B20914D2600F1C8FA /* FirefoxAccount.swift */; };
CE9D203520914D2600F1C8FA /* fxa.h in Headers */ = {isa = PBXBuildFile; fileRef = CE9D202F20914D2600F1C8FA /* fxa.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE5A6AEF220E2FD300B7F1BC /* RustProtobuf.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5A6AEE220E2FD300B7F1BC /* RustProtobuf.swift */; };
CEBACFC4220E22C80078D41C /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBACFC3220E22C80078D41C /* SwiftProtobuf.framework */; };
CECB395D20B5BE0200DB3ED4 /* RustPointer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CECB395B20B5BE0200DB3ED4 /* RustPointer.swift */; };
CEE1087620C5ADF9007048AC /* FxAError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE1087520C5ADF9007048AC /* FxAError.swift */; };
EBA8770C21F5FD5D004F63F0 /* base.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = EBA8770921F5FD5D004F63F0 /* base.xcconfig */; };
@ -21,13 +24,30 @@
EBE26B4B220B4DE300D1D99A /* SerialQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE26B4A220B4DE300D1D99A /* SerialQueue.swift */; };
/* End PBXBuildFile section */
/* Begin PBXBuildRule section */
CE2F4D40220DFF7B001ECF92 /* PBXBuildRule */ = {
isa = PBXBuildRule;
compilerSpec = com.apple.compilers.proxy.script;
filePatterns = "*.proto";
fileType = pattern.proxy;
isEditable = 1;
outputFiles = (
"$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).pb.swift",
);
script = "protoc --proto_path=$INPUT_FILE_DIR --swift_out=$DERIVED_FILE_DIR $INPUT_FILE_PATH\n";
};
/* End PBXBuildRule section */
/* Begin PBXFileReference section */
CE2F4D41220E0014001ECF92 /* ffi_types.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = ffi_types.proto; path = ../src/ffi_types.proto; sourceTree = "<group>"; };
CE5A6AEE220E2FD300B7F1BC /* RustProtobuf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustProtobuf.swift; sourceTree = "<group>"; };
CE7B4B8A20A36B0500FC4422 /* libfxaclient_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfxaclient_ffi.a; path = ../../../target/universal/debug/libfxaclient_ffi.a; sourceTree = "<group>"; };
CE9D202020914D0D00F1C8FA /* FxAClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FxAClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
CE9D202320914D0D00F1C8FA /* FxAClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FxAClient.h; sourceTree = "<group>"; };
CE9D202420914D0D00F1C8FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE9D202B20914D2600F1C8FA /* FirefoxAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirefoxAccount.swift; sourceTree = "<group>"; };
CE9D202F20914D2600F1C8FA /* fxa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fxa.h; sourceTree = "<group>"; };
CEBACFC3220E22C80078D41C /* SwiftProtobuf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftProtobuf.framework; path = ../../../Carthage/Build/iOS/SwiftProtobuf.framework; sourceTree = "<group>"; };
CECB395B20B5BE0200DB3ED4 /* RustPointer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RustPointer.swift; sourceTree = "<group>"; };
CEE1087520C5ADF9007048AC /* FxAError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FxAError.swift; sourceTree = "<group>"; };
EBA8770921F5FD5D004F63F0 /* base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
@ -43,6 +63,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CEBACFC4220E22C80078D41C /* SwiftProtobuf.framework in Frameworks */,
CE3E9D3520A36B63001B4B14 /* libfxaclient_ffi.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -53,6 +74,7 @@
CE9D201620914D0D00F1C8FA = {
isa = PBXGroup;
children = (
CE2F4D41220E0014001ECF92 /* ffi_types.proto */,
EBA8770921F5FD5D004F63F0 /* base.xcconfig */,
EBA8770A21F5FD5D004F63F0 /* debug.xcconfig */,
EBA8770B21F5FD5D004F63F0 /* release.xcconfig */,
@ -88,6 +110,7 @@
CE9D203720914D4800F1C8FA /* Frameworks */ = {
isa = PBXGroup;
children = (
CEBACFC3220E22C80078D41C /* SwiftProtobuf.framework */,
CE7B4B8A20A36B0500FC4422 /* libfxaclient_ffi.a */,
);
name = Frameworks;
@ -114,6 +137,7 @@
isa = PBXGroup;
children = (
CECB395B20B5BE0200DB3ED4 /* RustPointer.swift */,
CE5A6AEE220E2FD300B7F1BC /* RustProtobuf.swift */,
);
path = Rust;
sourceTree = "<group>";
@ -144,6 +168,7 @@
CE9D201E20914D0D00F1C8FA /* Resources */,
);
buildRules = (
CE2F4D40220DFF7B001ECF92 /* PBXBuildRule */,
);
dependencies = (
);
@ -219,9 +244,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CE2F4D42220E0014001ECF92 /* ffi_types.proto in Sources */,
CECB395D20B5BE0200DB3ED4 /* RustPointer.swift in Sources */,
EBE26B4B220B4DE300D1D99A /* SerialQueue.swift in Sources */,
EBE26B42220B3DF700D1D99A /* String+Free_FxAClient.swift in Sources */,
CE5A6AEF220E2FD300B7F1BC /* RustProtobuf.swift in Sources */,
EBE26B49220B4D0200D1D99A /* CommonErrors.swift in Sources */,
CE9D203120914D2600F1C8FA /* FirefoxAccount.swift in Sources */,
CEE1087620C5ADF9007048AC /* FxAError.swift in Sources */,

Просмотреть файл

@ -34,34 +34,23 @@ public enum FxAError: Error {
@discardableResult
public static func unwrap<T>(_ callback: (UnsafeMutablePointer<FxAErrorC>) throws -> T?) throws -> T {
var err = FxAErrorC(code: Int32(NoError), message: nil)
guard let result = try callback(&err) else {
if let fxaErr = FxAError.fromConsuming(err) {
throw fxaErr
}
throw ResultError.empty
}
// result might not be nil (e.g. it could be 0), while still indicating failure. Ultimately,
// `err` is the source of truth here.
let returnedVal = try callback(&err)
if let fxaErr = FxAError.fromConsuming(err) {
throw fxaErr
}
guard let result = returnedVal else {
throw ResultError.empty
}
return result
}
@discardableResult
public static func tryUnwrap<T>(_ callback: (UnsafeMutablePointer<FxAErrorC>) throws -> T?) throws -> T? {
var err = FxAErrorC(code: Int32(NoError), message: nil)
guard let result = try callback(&err) else {
if let fxaErr = FxAError.fromConsuming(err) {
throw fxaErr
}
return nil
}
// result might not be nil (e.g. it could be 0), while still indicating failure. Ultimately,
// `err` is the source of truth here.
let returnedVal = try callback(&err)
if let fxaErr = FxAError.fromConsuming(err) {
throw fxaErr
}
return result
return returnedVal
}
}

Просмотреть файл

@ -289,41 +289,30 @@ public struct Avatar {
public let isDefault: Bool
}
open class Profile: RustStructPointer<ProfileC> {
open class Profile: RustProtobuf<FfiTypes_Profile> {
open var uid: String {
get {
return String(cString: raw.pointee.uid)
return raw.uid
}
}
open var email: String {
get {
return String(cString: raw.pointee.email)
return raw.email
}
}
open var avatar: Avatar? {
get {
guard let pointer = raw.pointee.avatar else {
if !raw.hasAvatar {
return nil
}
return Avatar(url: String(cString: pointer), isDefault: raw.pointee.avatar_default == 0x01)
return Avatar(url: raw.avatar, isDefault: raw.avatarDefault)
}
}
open var displayName: String? {
get {
guard let pointer = raw.pointee.display_name else {
return nil
}
return String(cString: pointer)
}
}
override func cleanup(pointer: UnsafeMutablePointer<ProfileC>) {
queue.sync {
fxa_profile_free(raw)
}
return raw.hasDisplayName ? raw.displayName : nil
}
}

Просмотреть файл

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import Foundation
import SwiftProtobuf
open class RustProtobuf<T: SwiftProtobuf.Message> {
var raw: T
init(raw: ByteBuffer) {
if let data = raw.data {
let bytes = Data.init(bytes: data, count: Int(raw.len))
self.raw = try! T(serializedData: bytes)
} else {
self.raw = T.init()
}
fxa_bytebuffer_free(raw)
}
}

Просмотреть файл

@ -35,6 +35,14 @@ typedef struct FxAErrorC {
char *_Nullable message;
} FxAErrorC;
/*
A mapping of the ByteBuffer repr(C) Rust struct, from components/support/ffi/src/lib.rs.
*/
typedef struct ByteBuffer {
int64_t len;
uint8_t *_Nullable data;
} ByteBuffer;
typedef struct AccessTokenInfoC {
const char *const _Nonnull scope;
const char *const _Nonnull token;
@ -89,9 +97,9 @@ FirefoxAccountHandle fxa_new(const char *_Nonnull content_base,
const char *_Nonnull redirect_uri,
FxAErrorC *_Nonnull out);
ProfileC *_Nullable fxa_profile(FirefoxAccountHandle handle,
bool ignore_cache,
FxAErrorC *_Nonnull out);
ByteBuffer fxa_profile(FirefoxAccountHandle handle,
bool ignore_cache,
FxAErrorC *_Nonnull out);
FirefoxAccountHandle fxa_from_credentials(const char *_Nonnull content_base,
const char *_Nonnull client_id,
@ -115,7 +123,7 @@ SyncKeysC *_Nullable fxa_get_sync_keys(FirefoxAccountHandle handle,
void fxa_str_free(char *_Nullable ptr);
void fxa_free(FirefoxAccountHandle h, FxAErrorC *_Nonnull out);
void fxa_oauth_info_free(AccessTokenInfoC *_Nullable ptr);
void fxa_profile_free(ProfileC *_Nullable ptr);
void fxa_bytebuffer_free(ByteBuffer buffer);
void fxa_sync_keys_free(SyncKeysC *_Nullable ptr);
#endif /* fxa_h */

Просмотреть файл

@ -2,3 +2,4 @@
INFOPLIST_FILE = FxAClient/Info.plist
LIBRARY_SEARCH_PATHS = "../../../target/universal/$(buildvariant)"
FRAMEWORK_SEARCH_PATHS = "../../../Carthage/Build/iOS"

Просмотреть файл

@ -16,9 +16,10 @@
#[cfg(feature = "browserid")]
use crate::SyncKeys;
use crate::{AccessTokenInfo, Error, ErrorKind, Profile};
use crate::{ffi_types, AccessTokenInfo, Error, ErrorKind, Profile};
use ffi_support::{
destroy_c_string, opt_rust_string_to_c, rust_string_to_c, ErrorCode, ExternError, IntoFfi,
destroy_c_string, implement_into_ffi_protobuf, opt_rust_string_to_c, rust_string_to_c,
ErrorCode, ExternError, IntoFfi,
};
use std::os::raw::c_char;
@ -125,34 +126,14 @@ impl From<AccessTokenInfo> for AccessTokenInfoC {
}
}
#[repr(C)]
pub struct ProfileC {
uid: *mut c_char,
email: *mut c_char,
avatar: *mut c_char,
avatar_default: u8, // JNA dislikes booleans.
display_name: *mut c_char,
}
impl Drop for ProfileC {
fn drop(&mut self) {
unsafe {
destroy_c_string(self.uid);
destroy_c_string(self.email);
destroy_c_string(self.avatar);
destroy_c_string(self.display_name);
}
}
}
impl From<Profile> for ProfileC {
fn from(profile: Profile) -> Self {
ProfileC {
uid: rust_string_to_c(profile.uid),
email: rust_string_to_c(profile.email),
avatar: rust_string_to_c(profile.avatar),
avatar_default: profile.avatar_default as u8,
display_name: opt_rust_string_to_c(profile.display_name),
impl From<Profile> for ffi_types::Profile {
fn from(p: Profile) -> Self {
ffi_types::Profile {
avatar: Some(p.avatar),
avatar_default: Some(p.avatar_default),
display_name: p.display_name,
email: Some(p.email),
uid: Some(p.uid),
}
}
}
@ -179,4 +160,4 @@ macro_rules! implement_into_ffi_converting {
#[cfg(feature = "browserid")]
implement_into_ffi_converting!(SyncKeys, SyncKeysC);
implement_into_ffi_converting!(AccessTokenInfo, AccessTokenInfoC);
implement_into_ffi_converting!(Profile, ProfileC);
implement_into_ffi_protobuf!(ffi_types::Profile);

Просмотреть файл

@ -0,0 +1,11 @@
syntax = "proto2";
package ffi_types;
message Profile {
optional string uid = 1;
optional string email = 2;
optional string avatar = 3;
optional bool avatar_default = 4;
optional string display_name = 5;
}

Просмотреть файл

@ -23,6 +23,11 @@ mod config;
pub mod errors;
#[cfg(feature = "ffi")]
pub mod ffi;
// Include the `ffi_types` module, which is generated from ffi_types.proto.
pub mod ffi_types {
use prost_derive::Message; // https://github.com/danburkert/prost/issues/140
include!(concat!(env!("OUT_DIR"), "/ffi_types.rs"));
}
mod http_client;
#[cfg(feature = "browserid")]
mod login_sm;

Просмотреть файл

@ -1,7 +1,7 @@
[package]
name = "ffi-support"
edition = "2018"
version = "0.1.5"
version = "0.1.6"
authors = ["Thom Chiovoloni <tchiovoloni@mozilla.com>"]
description = "A crate to help expose Rust functions over the FFI."
repository = "https://github.com/mozilla/application-services"
@ -16,6 +16,7 @@ travis-ci = { repository = "mozilla/application-services" }
[features]
default = []
log_backtraces = ["backtrace"]
prost_support = ["prost"]
[dependencies]
serde_json = "1.0.32"
@ -29,3 +30,9 @@ failure_derive = "0.1.5"
optional = true
version = "0.3.9"
[dependencies.prost]
optional = true
version = "0.4"
[package.metadata.docs.rs]
features = ["prost_support"]

Просмотреть файл

@ -343,3 +343,113 @@ fn init_backtraces_once() {
#[cfg(not(feature = "log_backtraces"))]
fn init_backtraces_once() {}
/// ByteBuffer is a struct that represents an array of bytes to be sent over the FFI boundaries.
/// There are several cases when you might want to use this, but the primary one for us
/// is for returning protobuf-encoded data to Swift and Java. The type is currently rather
/// limited (implementing almost no functionality), however in the future it may be
/// more expanded.
///
/// ## Caveats
///
/// Note that the order of the fields is `len` (an i64) then `data` (a `*mut u8`), getting
/// this wrong on the other side of the FFI will cause memory corruption and crashes.
/// `i64` is used for the length instead of `u64` and `usize` because JNA has intero
/// issues with both these types.
///
/// You should probably not use this type to pass data into Rust unless the ByteBuffer
/// was allocated by Rust code: ByteBuffer assumes it owns the underlying data,
/// and will Drop it.
///
/// ## Layout/fields
///
/// This struct's field are not `pub` (mostly so that we can soundly implement `Send`, but also so
/// that we can verify rust users are constructing them appropriately), the fields, their types, and
/// their order are *very much* a part of the public API of this type. Consumers on the other side
/// of the FFI will need to know its layout.
///
/// If this were a C struct, it would look like
///
/// ```c,no_run
/// struct ByteBuffer {
/// int64_t len;
/// uint8_t *data; // note: nullable
/// };
/// ```
///
/// In rust, there are two fields, in this order: `len: i64`, and `data: *mut u8`.
///
/// ### Description of fields
///
/// `data` is a pointer to an array of `len` bytes. Not that data can be a null pointer and therefore
/// should be checked.
///
/// The bytes array is allocated on the heap and must be freed on it as well. Critically, if there are multiple rust
/// packages using being used in the same application, it *must be freed on the same heap that
/// allocated it*, or you will corrupt both heaps.
///
/// Typically, this object is managed on the other side of the FFI (on the "FFI consumer"), which
/// means you must expose a function to release the resources of `data` which can be done easily
/// using the [`define_bytebuffer_destructor!`] macro provided by this crate.
#[repr(C)]
pub struct ByteBuffer {
len: i64,
data: *mut u8,
}
impl From<Vec<u8>> for ByteBuffer {
#[inline]
fn from(bytes: Vec<u8>) -> Self {
Self::from_vec(bytes)
}
}
impl ByteBuffer {
/// Creates a `ByteBuffer` instance from a `Vec` instance, the contents of the vector will be
/// forgotten by Rust's ownership system.
/// `drop` must be called later to reclaim this memory or it will be leaked.
///
/// ## Caveats
///
/// This will panic if the buffer length (`usize`) cannot fit into a `i64`.
#[inline]
pub fn from_vec(bytes: Vec<u8>) -> Self {
let mut buf = bytes.into_boxed_slice();
let data = buf.as_mut_ptr();
let len = buf.len();
assert!(
len == (len as i64) as usize,
"buffer length cannot fit into a i64."
);
std::mem::forget(buf);
Self {
data,
len: len as i64,
}
}
}
impl Drop for ByteBuffer {
#[inline]
fn drop(&mut self) {
if !self.data.is_null() {
unsafe {
drop(Vec::from_raw_parts(
self.data,
self.len as usize,
self.len as usize,
));
}
}
}
}
impl Default for ByteBuffer {
#[inline]
fn default() -> Self {
Self {
len: 0 as i64,
data: ::std::ptr::null_mut(),
}
}
}

Просмотреть файл

@ -73,6 +73,41 @@ macro_rules! implement_into_ffi_by_json {
)*}
}
/// Implements [`IntoFfi`] for the provided types (more than one may be passed in) implementing
/// `prost::Message` (protobuf auto-generated type) by converting to the type to a [`ByteBuffer`].
/// This [`ByteBuffer`] should later be passed by value.
///
/// Note: Each type passed in must implement or derive `prost::Message`.
#[cfg(feature = "prost_support")]
#[macro_export]
macro_rules! implement_into_ffi_protobuf {
($($FFIType:ty),* $(,)*) => {$(
unsafe impl IntoFfi for $FFIType where $FFIType: prost::Message {
type Value = $crate::ByteBuffer;
fn ffi_default() -> Self::Value {
Default::default()
}
fn into_ffi_value(self) -> Self::Value {
$crate::convert_protobuf_to_byte_buffer(&self)
}
}
)*}
}
// Needs to be pub so the macro can call it, but that's all.
#[cfg(feature = "prost_support")]
#[doc(hidden)]
#[inline]
pub fn convert_protobuf_to_byte_buffer<T: prost::Message>(value: &T) -> crate::ByteBuffer {
let mut bytes = Vec::new();
bytes.reserve(value.encoded_len());
// Unwrap is safe, since we have reserved sufficient capacity in the vector.
value.encode(&mut bytes).unwrap();
bytes.into()
}
/// For a number of reasons (name collisions are a big one, but, it also wouldn't work on all
/// platforms), we cannot export `extern "C"` functions from this library. However, it's pretty
/// common to want to free strings allocated by rust, so many libraries will need this, so we
@ -148,6 +183,36 @@ macro_rules! define_box_destructor {
};
}
/// Define a (public) destructor for the ByteBuffer type.
///
/// ## Caveats
///
/// If you're using multiple separately compiled rust libraries in your application, it's critical
/// that you are careful to only ever free `ByteBuffer` instances allocated by a Rust library using
/// the same rust library. Passing them to a different Rust library's string destructor will cause
/// you to corrupt multiple heaps.
/// One common ByteBuffer destructor is defined per Rust library.
///
/// Also, to avoid name collisions, it is strongly recommended that you provide an name for this
/// function unique to your library. (This is true for all functions you expose).
///
/// ## Example
///
/// ```rust
/// # use ffi_support::define_bytebuffer_destructor;
/// define_bytebuffer_destructor!(mylib_destroy_bytebuffer);
/// ```
#[macro_export]
macro_rules! define_bytebuffer_destructor {
($destructor_name:ident) => {
#[no_mangle]
pub extern "C" fn $destructor_name(v: $crate::ByteBuffer) {
drop(v);
}
};
}
/// Define a (public) destructor for a type that lives inside a lazy_static
/// [`ConcurrentHandleMap`].
///

Просмотреть файл

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
CE08288320AB319A006B8D84 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE08288220AB319A006B8D84 /* ProfileView.swift */; };
CE08288620AB3315006B8D84 /* FxAClient.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEC659D220AB2F6600B5D71C /* FxAClient.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CE1D3134220E26E500A6A85B /* SwiftProtobuf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE1D3133220E26E500A6A85B /* SwiftProtobuf.framework */; };
CE1D3135220E26E500A6A85B /* SwiftProtobuf.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE1D3133220E26E500A6A85B /* SwiftProtobuf.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
CE3BA07020AB2889005B1FD6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3BA06F20AB2889005B1FD6 /* AppDelegate.swift */; };
CE3BA07220AB2889005B1FD6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE3BA07120AB2889005B1FD6 /* ViewController.swift */; };
CE3BA07720AB288A005B1FD6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE3BA07620AB288A005B1FD6 /* Assets.xcassets */; };
@ -23,6 +25,7 @@
dstSubfolderSpec = 10;
files = (
CE08288620AB3315006B8D84 /* FxAClient.framework in Embed Frameworks */,
CE1D3135220E26E500A6A85B /* SwiftProtobuf.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -31,6 +34,7 @@
/* Begin PBXFileReference section */
CE08288220AB319A006B8D84 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
CE1D3133220E26E500A6A85B /* SwiftProtobuf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftProtobuf.framework; path = Carthage/Build/iOS/SwiftProtobuf.framework; sourceTree = "<group>"; };
CE3BA06C20AB2889005B1FD6 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
CE3BA06F20AB2889005B1FD6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CE3BA07120AB2889005B1FD6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@ -48,6 +52,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CE1D3134220E26E500A6A85B /* SwiftProtobuf.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -57,6 +62,7 @@
CE3BA06320AB2889005B1FD6 = {
isa = PBXGroup;
children = (
CE1D3133220E26E500A6A85B /* SwiftProtobuf.framework */,
EBA8770F21F602C6004F63F0 /* base.xcconfig */,
EBA8771021F602C6004F63F0 /* debug.xcconfig */,
EBA8771121F602C7004F63F0 /* release.xcconfig */,
@ -192,6 +198,14 @@
baseConfigurationReference = EBA8771021F602C6004F63F0 /* debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
};
name = Debug;
};
@ -200,6 +214,14 @@
baseConfigurationReference = EBA8771121F602C7004F63F0 /* release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
};
name = Release;
};