Skip to content

Feature: Add @encode decorator#1899

Merged
timotheeguerin merged 11 commits intomicrosoft:mainfrom
timotheeguerin:feature/encode
May 4, 2023
Merged

Feature: Add @encode decorator#1899
timotheeguerin merged 11 commits intomicrosoft:mainfrom
timotheeguerin:feature/encode

Conversation

@timotheeguerin
Copy link
Copy Markdown
Member

@timotheeguerin timotheeguerin commented May 3, 2023

fix #282

Examples

Specify uuid, email, ipv4, ipv6

model Bar {
  @format("uuid") id: string;
  @format("email") userEmail: string;
  @format("ipv4") ipv4: string;
  @format("ipv6") ipv6: string;
}

Specify base64 or base64url encoding

model Bar {
  @encode("base64") data: bytes;
  @encode("base64url") data2: string;

  // This is how it is currently. So this would have to change
  @format("base64") data: bytes;
  @format("base64url") data2: string;
}

Specify serialization using rfc3339 standard

model Bar {
  @encode("rfc3339")
  createdAt: utcDateTime;

  @encode("rfc3339")
  modifiedAt: offsetDateTime;

  @encode("rfc3339")
  runtime: duration;

  // We could also technically represent the datetime as a string and then we'd use the `@format` decorator to specify the pattern of that string
  @format("date-time")
  createdAtButString: string;
}

Specify serialization using rfc7231 standard

model Bar {
  @encode("rfc7231")
  createdAt: utcDateTime;

  @encode("rfc7231")
  modifiedAt: offsetDateTime;

  @encode("rfc7231")
  runtime: duration;

  @format("date-time-rfc7231")
  createdAtButString: string;
}

Specify serialization using unixTimestamp

model Bar {
  @encode("unixTimestamp", int32)
  createdAt: utcDateTime;

  @encode("unixTimestamp", int32)  // invalid
  modifiedAt: offsetDateTime;

  @encode("unixTimestamp", int32) // invalid
  runtime: duration;


}

Specify Duration serialized as seconds

model Bar {
  @encode("seconds", float64)
  runtimeAsDouble: duration;
  @encode("seconds", int32)
  runtimeAsInt: duration;
}

Formats that move to @encode

Deprecate using @format on bytes

  • base64url
  • base64

Logic for emitter:

  • Generated type: use the actual typespec type
  • Over the wire type:
    • lookup for @encode decorator
      • if absent use typespec type (or default way of serializing that type)
      • if present respect type provided in @encode

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2023

Changes in this PR will be published to the following url to try(check status of TypeSpec Pull Request Try It pipeline for publish status):
Playground: https://cadlplayground.z22.web.core.windows.net/prs/1899/

Website: https://cadlwebsite.z1.web.core.windows.net/prs/1899/

@MaryGao
Copy link
Copy Markdown
Member

MaryGao commented May 10, 2023

@timotheeguerin Could you help on the differences for below two statements? Are they equivalent?

// Statement 1
model Bar {
  @encode("rfc7231")
  createdAt: utcDateTime;
}

// Statement 2
model Bar {
  @format("date-time-rfc7231")
  createdAt: string;
}

@timotheeguerin
Copy link
Copy Markdown
Member Author

Hey @MaryGao they are kind of equivalent for what it means over the wire but they are not equivalent for what you’d expect in the client.

In the encode case you are saying that property is a date time conceptually and so would want to represent that in the client/server code.

in the format case you are saying it is a string conceptually but it happens to be in the pattern of a rfc7231 date time. So in this case the client/server should only represent it as a string.

i would think of format as a know pattern for string and that’s it. You shouldn’t do anything special about but validation(if you are doing validation)

@MaryGao
Copy link
Copy Markdown
Member

MaryGao commented Sep 11, 2023

@timotheeguerin One more follow-up question, what is the expected string format if a typespec utcDateTime without any encode? "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'" or others ? the same question for offsetDateTime?

model Bar {
  createdAt: utcDateTime;
  endAt: offsetDateTime;
}

@timotheeguerin
Copy link
Copy Markdown
Member Author

@MaryGao it depends on the protocol and other things, For http there is documentation about all the default encoding of non primitive types here https://microsoft.github.io/typespec/next/standard-library/http/encoding#utcdatetime-and-offsetdatetime

@qiaozha
Copy link
Copy Markdown
Member

qiaozha commented Sep 12, 2023

@timotheeguerin I might miss something, in the offsetDateTime description, it gives an example of "April 10th at 3:00am in PST" which should be rfc7231 by default as I understand it.

https://github.com/microsoft/typespec/blob/main/packages/compiler/lib/lib.tsp#L108-L111

but in the documentation, it says the default format for offsetDateTime is something like "2022-10-25T07:20:50.52+07:00" which by the way is also not the standard rfc3339 format if I understand correctly ?

@timotheeguerin
Copy link
Copy Markdown
Member Author

timotheeguerin commented Sep 12, 2023

In the first doc you linked it just shows the concept of a zoned date time that string is not rfc7231 either.

@bterlson
Copy link
Copy Markdown
Member

It is rfc7231 only when used as a header, otherwise rfc3339. Can you point out the part of the example that is invalid?

@qiaozha
Copy link
Copy Markdown
Member

qiaozha commented Sep 12, 2023

"+07:00" inside "2022-10-25T07:20:50.52+07:00" ?

@timotheeguerin
Copy link
Copy Markdown
Member Author

It is no? https://ijmacd.github.io/rfc3339-iso8601/
How else do you expect the offset to be specified?

@bterlson
Copy link
Copy Markdown
Member

You can see the offset syntax in the grammar here also: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6

@qiaozha
Copy link
Copy Markdown
Member

qiaozha commented Sep 12, 2023

Got it, Thank you all for the pointers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement decorator to support date serialization format

5 participants