This is a work in progress!
Parse the metadata XML describing an SAP OData service and generate basic Rust entities for each EDM type:
ComplexType
EntityType
FunctionImport
TODO
Currently when generating a Rust
struct
, only theName
andType
properties are extracted from the XML<EntityType>
declaration.
Consider how the other XML attribute values and SAP annotations could be made available within the Ruststruct
.
In the Cargo.toml
of your application, define an entry in [build-dependencies]
that points to the parse-sap-odata
crate:
toml
[build-dependencies]
parse-sap-odata = "^1.1.0"
Your app will also (almost certainly) require these dependencies
toml
[dependencies]
rust_decimal = "^1.30"
uuid = "^1.4"
chrono = "^0.4"
In your app's build script (build.rs
), run the generator for your desired OData service:
```rust use parsesapodata::utils::parseodata::gensrc;
fn main() { gensrc( metadatafilename: "gwsamplebasic", namespace: "GWSAMPLE_BASIC" ); } ```
See the Rust documentation page for build scripts for more information.
All metadata XML for the OData services your app consumes must be located in the ./odata
directory immediately under your app's top level directory.
Using the above example from SAP's Dev Center server, the OData metadata XML for service GWSAMPLE_BASIC
must be located in file ./odata/gwsample_basic.xml
If cargo
detects a build.rs
file in your project/crate, then it automatically populates the environment variable OUT_DIR
.
This variable then points to the directory into which all build script output is written.
The default directory name is target/debug/build/<your_package_name>/out
, and this is where you can find the generated struct
declarations for the OData service.
You can specify your own value for OUT_DIR
either by passing a value to cargo
's --out_dir
flag, or by defining your own location in a config.toml
file in the ./.cargo
directory.
See Cargo Configuration for more details.
All generated struct
s implement #[derive(Clone, Debug, Default)]
Since cargo
runs the build script before compiling your application code, the source code of your application can reference the generated structs
like this:
```rust include!(concat!(env!("OUTDIR"), "/gwsamplebasic.rs"));
fn main() { let bp: BusinessPartner = Default::default(); println!("{:#?}", bp); } ```
In the event an Entity Type definition uses a complex type, then the complex type is first created as a Rust struct
.
The field in Rust struct
that has this complex type is then defined using this struct
.
An example of this is the Address
property.
```xml
```
The Rust struct
name is generated by trimming the namespace qualifier and (if present) the CT_
prefix
xml
<ComplexType Name="CT_Address">
<Property Name="City" Type="Edm.String" MaxLength="40" sap:label="City" sap:semantics="city"/>
<Property Name="PostalCode" Type="Edm.String" MaxLength="10" sap:label="Postal Code" sap:semantics="zip"/>
<Property Name="Street" Type="Edm.String" MaxLength="60" sap:label="Street" sap:semantics="street"/>
<Property Name="Building" Type="Edm.String" MaxLength="10" sap:label="Building"/>
<Property Name="Country" Type="Edm.String" MaxLength="3" sap:label="Country" sap:semantics="country"/>
<Property Name="AddressType" Type="Edm.String" MaxLength="2" sap:label="Address Type"/>
</ComplexType>
So the above XML definition becomes:
```rust
pub struct Address {
pub addresstype: Option
The metadata for the GWSAMPLE_BASIC
OData service contains the following complex type:
xml
<ComplexType Name="CT_String">
<Property Name="String" Type="Edm.String" Nullable="false" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
</ComplexType>
Allowing for the current situation in which additional attribute values and SAP Annotations are not preserved, this particular type turns out not to be complex at all — its just a String
.
In such cases, fields declared to be of these "simple" complex types (such as CT_String
), are collapsed down to the Rust native type of the single inner property — which in this example is simply a String
.
You must already have a userid and password for the SAP Dev Center server sapes5.sapdevcenter.com
build_test_crate
subdirectory..env
file containing your userid and password in the following format
env
SAP_USER=<your userid>
SAP_PASSWORD=<your password>
cargo run
BusinessPartnerSet
belonging to the OData service GWSAMPLE_BASIC
displayed in JSON format.```json { "d": { "results": [ { "metadata": { "id": "https://SAPES5.SAPDEVCENTER.COM:443/sap/opu/odata/iwbep/GWSAMPLEBASIC/BusinessPartnerSet('0100000000')", "uri": "https://SAPES5.SAPDEVCENTER.COM:443/sap/opu/odata/iwbep/GWSAMPLEBASIC/BusinessPartnerSet('0100000000')", "type": "GWSAMPLEBASIC.BusinessPartner", "etag": "W/\"datetime'2023-08-09T05%3A31%3A57.3627400'\"" }, "Address": { "metadata": { "type": "GWSAMPLEBASIC.CT_Address" }, "City": "Walldorf", "PostalCode": "69190", "Street": "Dietmar-Hopp-Allee", "Building": "16", "Country": "DE", "AddressType": "02" }, "BusinessPartnerID": "0100000000",