Skip to content

Commit

Permalink
[typeshare] Support linux-arm64 and support u64 (#1)
Browse files Browse the repository at this point in the history
## Description
* Switching build over to `zigbuild` to support linux arm64 variant
* Porting over 1Password#140 to support large number
* Adding some default overrides to include base types for stuff such as `HashSet`

## Test Plan
* Typeshare built for repo

## Revert Plan
* Revert
  • Loading branch information
naveenOnarayanan authored Nov 6, 2024
1 parent da98c89 commit 2e2b203
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 79 deletions.
37 changes: 32 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,23 @@ jobs:
include:
- os: ubuntu-20.04
dist-args: --artifacts=global
target: ''
install-dist: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.0.4/cargo-dist-v0.0.4-installer.sh | sh
- os: macos-11
dist-args: --artifacts=local --target=aarch64-apple-darwin --target=x86_64-apple-darwin
target: 'aarch64-apple-darwin x86_64-apple-darwin'
install-dist: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.0.4/cargo-dist-v0.0.4-installer.sh | sh
- os: ubuntu-20.04
dist-args: --artifacts=local --target=x86_64-unknown-linux-gnu
target: 'x86_64-unknown-linux-gnu'
install-dist: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.0.4/cargo-dist-v0.0.4-installer.sh | sh
- os: ubuntu-20.04
dist-args: --artifacts=local --target=aarch64-unknown-linux-gnu
target: 'aarch64-unknown-linux-gnu'
install-dist: curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.0.4/cargo-dist-v0.0.4-installer.sh | sh
- os: windows-2019
dist-args: --artifacts=local --target=x86_64-pc-windows-msvc
target: 'x86_64-pc-windows-msvc'
install-dist: irm https://github.com/axodotdev/cargo-dist/releases/download/v0.0.4/cargo-dist-v0.0.4-installer.ps1 | iex

runs-on: ${{ matrix.os }}
Expand All @@ -108,17 +116,36 @@ jobs:
- name: Install cargo-dist
run: ${{ matrix.install-dist }}
- name: Run cargo-dist
if: ${{ matrix.target != '' }}
# This logic is a bit janky because it's trying to be a polyglot between
# powershell and bash since this will run on windows, macos, and linux!
# The two platforms don't agree on how to talk about env vars but they
# do agree on 'cat' and '$()' so we use that to marshal values between commands.
run: |
# Actually do builds and make zips and whatnot
cargo dist build --tag=${{ github.ref_name }} --output-format=json ${{ matrix.dist-args }} > dist-manifest.json
echo "dist ran successfully"
pip3 install ziglang
cargo install cargo-zigbuild
rustup target add ${{ matrix.target }}
cargo zigbuild --target ${{ matrix.target }} --release
# Set binary name to typeshare
BINARY_NAME="typeshare"
TARGET_DIR="target/${{ matrix.target }}/release"

# Create zip directory
mkdir -p "dist"

# Create zip file with binary
ZIP_NAME="${BINARY_NAME}-${{ github.ref_name }}-${{ matrix.target }}.zip"
cd ${TARGET_DIR} && zip "../../../dist/${ZIP_NAME}" "${BINARY_NAME}${BINARY_SUFFIX}"
cd ../../..

# Create manifest file similar to cargo-dist
echo "{\"artifacts\": [{\"path\": \"dist/${ZIP_NAME}\"}]}" > dist-manifest.json

echo "Build complete, contents of dist-manifest.json:"
cat dist-manifest.json
# Parse out what we just built and upload it to the Github Release™
# Upload to release
cat dist-manifest.json | jq --raw-output ".artifacts[]?.path | select( . != null )" > uploads.txt
echo "uploading..."
cat uploads.txt
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ci = ["github"]
installers = ["shell", "powershell"]
# Target platforms to build apps for (Rust target-triple syntax)
targets = [
"aarch64-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
Expand Down
10 changes: 10 additions & 0 deletions core/data/tests/can_override_disallowed_types/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[typeshare]
struct DisallowedType {
#[typeshare(typescript(type = "bigint"))]
disallowed_type: u64,
#[typeshare(typescript(type = "number"))]
another_disallowed_type: i64,
#[typeshare(typescript(type = "string"))]
#[serde(with = "my_string_serde_impl")]
disallowed_type_serde_with: u64,
}
9 changes: 9 additions & 0 deletions core/data/tests/can_override_disallowed_types/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package proto

import "encoding/json"

type DisallowedType struct {
DisallowedType uint64 `json:"disallowed_type"`
AnotherDisallowedType int64 `json:"another_disallowed_type"`
DisallowedTypeSerdeWith uint64 `json:"disallowed_type_serde_with"`
}
12 changes: 12 additions & 0 deletions core/data/tests/can_override_disallowed_types/output.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.agilebits.onepassword

import kotlinx.serialization.Serializable
import kotlinx.serialization.SerialName

@Serializable
data class DisallowedType (
val disallowed_type: ULong,
val another_disallowed_type: Long,
val disallowed_type_serde_with: ULong
)

19 changes: 19 additions & 0 deletions core/data/tests/can_override_disallowed_types/output.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.agilebits

package object onepassword {

type UByte = Byte
type UShort = Short
type UInt = Int
type ULong = Int

}
package onepassword {

case class DisallowedType (
disallowed_type: ULong,
another_disallowed_type: Long,
disallowed_type_serde_with: ULong
)

}
13 changes: 13 additions & 0 deletions core/data/tests/can_override_disallowed_types/output.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

public struct DisallowedType: Codable {
public let disallowed_type: UInt64
public let another_disallowed_type: Int64
public let disallowed_type_serde_with: UInt64

public init(disallowed_type: UInt64, another_disallowed_type: Int64, disallowed_type_serde_with: UInt64) {
self.disallowed_type = disallowed_type
self.another_disallowed_type = another_disallowed_type
self.disallowed_type_serde_with = disallowed_type_serde_with
}
}
6 changes: 6 additions & 0 deletions core/data/tests/can_override_disallowed_types/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface DisallowedType {
disallowed_type: bigint;
another_disallowed_type: number;
disallowed_type_serde_with: string;
}

1 change: 1 addition & 0 deletions core/src/language/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ impl Language for Go {
SpecialRustType::U32 => "uint32".into(),
SpecialRustType::I54 | SpecialRustType::I64 => "int64".into(),
SpecialRustType::U53 | SpecialRustType::U64 => "uint64".into(),
SpecialRustType::U128 => "uint128".into(),
SpecialRustType::Bool => "bool".into(),
SpecialRustType::F32 => "float32".into(),
SpecialRustType::F64 => "float64".into(),
Expand Down
1 change: 1 addition & 0 deletions core/src/language/kotlin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ impl Language for Kotlin {
SpecialRustType::Bool => "Boolean".into(),
SpecialRustType::F32 => "Float".into(),
SpecialRustType::F64 => "Double".into(),
SpecialRustType::U128 => "BigInteger".into(),
})
}

Expand Down
1 change: 1 addition & 0 deletions core/src/language/scala.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl Language for Scala {
SpecialRustType::Bool => "Boolean".into(),
SpecialRustType::F32 => "Float".into(),
SpecialRustType::F64 => "Double".into(),
SpecialRustType::U128 => "BigInt".into(),
})
}

Expand Down
1 change: 1 addition & 0 deletions core/src/language/swift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ impl Language for Swift {
SpecialRustType::Bool => "Bool".into(),
SpecialRustType::F32 => "Float".into(),
SpecialRustType::F64 => "Double".into(),
SpecialRustType::U128 => "UInt128".into(),
})
}

Expand Down
8 changes: 4 additions & 4 deletions core/src/language/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ impl Language for TypeScript {
SpecialRustType::U64
| SpecialRustType::I64
| SpecialRustType::ISize
| SpecialRustType::USize => {
panic!("64 bit types not allowed in Typeshare")
}
| SpecialRustType::U128
| SpecialRustType::USize => Ok("number".into())
}
}

Expand Down Expand Up @@ -178,8 +177,9 @@ impl Language for TypeScript {
w: &mut dyn Write,
imports: ScopedCrateTypes<'_>,
) -> std::io::Result<()> {
writeln!(w, "import type {{ HashSet }} from \"./base\";")?;
for (path, ty) in imports {
write!(w, "import {{ ")?;
write!(w, "import type {{ ")?;
let ty_list = ty.iter().join(", ");
write!(w, "{ty_list}")?;
writeln!(w, " }} from \"./{path}\";")?;
Expand Down
15 changes: 12 additions & 3 deletions core/src/rust_types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use log::debug;
use quote::ToTokens;
use std::collections::BTreeSet;
use std::str::FromStr;
Expand Down Expand Up @@ -206,6 +207,8 @@ pub enum SpecialRustType {
I32,
/// Represents `i64`
I64,
/// Represents `u128`
U128,
/// Represents `u8`
U8,
/// Represents `u16`
Expand Down Expand Up @@ -257,6 +260,7 @@ impl TryFrom<&syn::Type> for RustType {
type Error = RustTypeParseError;

fn try_from(ty: &syn::Type) -> Result<Self, Self::Error> {
debug!("Parsing type: {}", ty.to_token_stream());
Ok(match ty {
syn::Type::Tuple(tuple) if tuple.elems.iter().count() == 0 => {
Self::Special(SpecialRustType::Unit)
Expand Down Expand Up @@ -305,12 +309,14 @@ impl TryFrom<&syn::Type> for RustType {
"u16" => Self::Special(SpecialRustType::U16),
"u32" => Self::Special(SpecialRustType::U32),
"U53" => Self::Special(SpecialRustType::U53),
"u64" | "i64" | "usize" | "isize" => {
return Err(RustTypeParseError::UnsupportedType(vec![id]))
}
"u64" => Self::Special(SpecialRustType::U64),
"usize" => Self::Special(SpecialRustType::USize),
"u128" => Self::Special(SpecialRustType::U128),
"i8" => Self::Special(SpecialRustType::I8),
"i16" => Self::Special(SpecialRustType::I16),
"i32" => Self::Special(SpecialRustType::I32),
"i64" => Self::Special(SpecialRustType::I64),
"isize" => Self::Special(SpecialRustType::ISize),
"I54" => Self::Special(SpecialRustType::I54),
"f32" => Self::Special(SpecialRustType::F32),
"f64" => Self::Special(SpecialRustType::F64),
Expand Down Expand Up @@ -488,6 +494,7 @@ impl SpecialRustType {
| Self::F32
| Self::F64
| Self::I54
| Self::U128
| Self::U53 => ty == self.id(),
}
}
Expand Down Expand Up @@ -518,6 +525,7 @@ impl SpecialRustType {
Self::USize => "usize",
Self::U53 => "U53",
Self::I54 => "I54",
Self::U128 => "u128",
}
}
/// Iterate over the generic parameters for this type. Returns an empty iterator
Expand All @@ -541,6 +549,7 @@ impl SpecialRustType {
| Self::U16
| Self::U32
| Self::U64
| Self::U128
| Self::ISize
| Self::USize
| Self::Bool
Expand Down
15 changes: 11 additions & 4 deletions core/src/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,33 +265,38 @@ impl<'ast, 'a> Visit<'ast> for TypeShareVisitor<'a> {

/// Collect rust structs.
fn visit_item_struct(&mut self, i: &'ast syn::ItemStruct) {
debug!("Visiting {}", i.ident);
debug!("Visiting item {}", i.ident);
if has_typeshare_annotation(&i.attrs) && self.target_os_accepted(&i.attrs) {
debug!("\tParsing {}", i.ident);
self.collect_result(parse_struct(i, self.target_os));
debug!("\tParsed {}", i.ident);
}

debug!("Visited item {}", i.ident);
syn::visit::visit_item_struct(self, i);
}

/// Collect rust enums.
fn visit_item_enum(&mut self, i: &'ast syn::ItemEnum) {
debug!("Visiting {}", i.ident);
debug!("Visiting enum {}", i.ident);
if has_typeshare_annotation(&i.attrs) && self.target_os_accepted(&i.attrs) {
debug!("\tParsing {}", i.ident);
self.collect_result(parse_enum(i, self.target_os));
debug!("\tParsed {}", i.ident);
}
debug!("Visited enum {}", i.ident);

syn::visit::visit_item_enum(self, i);
}

/// Collect rust type aliases.
fn visit_item_type(&mut self, i: &'ast syn::ItemType) {
debug!("Visiting {}", i.ident);
debug!("Visiting type {}", i.ident);
if has_typeshare_annotation(&i.attrs) && self.target_os_accepted(&i.attrs) {
debug!("\tParsing {}", i.ident);
self.collect_result(parse_type_alias(i));
debug!("\tParsed {}", i.ident);
}
debug!("Visited type {}", i.ident);

syn::visit::visit_item_type(self, i);
}
Expand All @@ -308,9 +313,11 @@ impl<'ast, 'a> Visit<'ast> for TypeShareVisitor<'a> {
// }

fn visit_file(&mut self, i: &'ast syn::File) {
debug!("Visiting file {}", self.parsed_data.file_name);
if self.target_os_accepted(&i.attrs) {
syn::visit::visit_file(self, i);
}
debug!("Visited file {}", self.parsed_data.file_name);
}
}

Expand Down
63 changes: 0 additions & 63 deletions core/tests/agnostic_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::io::Write;
use typeshare_core::{
language::{CrateTypes, Language, TypeScript},
parser::{self, ParseError},
rust_types::RustTypeParseError,
ProcessInputError,
};
/// Parse and generate types for a single Rust input file.
Expand Down Expand Up @@ -33,68 +32,6 @@ pub fn process_input(
Ok(())
}

mod blocklisted_types {
use std::collections::HashMap;

use super::*;

fn assert_type_is_blocklisted(ty: &str, blocklisted_type: &str) {
let source = format!(
r##"
#[typeshare]
#[serde(default, rename_all = "camelCase")]
pub struct Foo {{
pub bar: {ty},
}}
"##,
ty = ty
);

let mut out: Vec<u8> = Vec::new();
assert!(matches!(
process_input(&source, &mut TypeScript::default(), &HashMap::new(), &mut out),
Err(ProcessInputError::ParseError(
ParseError::RustTypeParseError(RustTypeParseError::UnsupportedType(contents))
)) if contents == vec![blocklisted_type.to_owned()]
));
}

#[test]
fn test_i64_blocklisted_struct() {
assert_type_is_blocklisted("i64", "i64");
}

#[test]
fn test_u64_blocklisted_struct() {
assert_type_is_blocklisted("u64", "u64");
}

#[test]
fn test_isize_blocklisted_struct() {
assert_type_is_blocklisted("isize", "isize");
}

#[test]
fn test_usize_blocklisted_in_struct() {
assert_type_is_blocklisted("usize", "usize");
}

#[test]
fn test_optional_blocklisted_struct() {
assert_type_is_blocklisted("Option<i64>", "i64");
}

#[test]
fn test_vec_blocklisted_struct() {
assert_type_is_blocklisted("Vec<i64>", "i64");
}

#[test]
fn test_hashmap_blocklisted_struct() {
assert_type_is_blocklisted("HashMap<String, i64>", "i64");
}
}

mod serde_attributes_on_enums {
use std::collections::HashMap;

Expand Down
Loading

0 comments on commit 2e2b203

Please sign in to comment.