Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This command creates a new IceRPC client application in directory `MyProtobufCli

Let's examine each file:

### proto/greeter.proto - the contract
### proto/visitor_center/greeter.proto - the contract

This file is (and must be) identical or almost identical to the `greeter.proto`
we used for the server:
Expand Down Expand Up @@ -127,7 +127,7 @@ service that implements `Greeter`.
With this code, the address of the target service (or
[service address][service-address]) is the default for `Greeter`, namely
`icerpc:/visitor_center.Greeter`. It matches the route we created in the server.
We could also create the same proxy with an explicit service address:
We could also create the same client with an explicit service address:

```csharp
var greeter = new GreeterClient(pipeline, new Uri("icerpc:/visitor_center.Greeter"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ This command creates a new IceRPC server application in directory `MyProtobufSer

Let's examine each file:

### proto/greeter.proto - the contract
### proto/visitor_center/greeter.proto - the contract

This file holds the contract between our client and server applications,
specified with the [Protobuf] language.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This command creates a new IceRPC client application in directory `MySliceClient

Let's examine each file:

### slice/Greeter.slice - the contract
### slice/VisitorCenter/Greeter.slice - the contract

This file is (and must be) identical or almost identical to the `Greeter.slice`
we used for the server:
Expand Down Expand Up @@ -149,7 +149,7 @@ separate IceRpc NuGet packages:

- [IceRpc.Slice] - the IceRPC + Slice integration package
- [IceRpc.Slice.Tools] - the package that compiles `Greeter.slice` into
`generated/Greeter.IceRpc.cs`
`generated/Greeter.cs` and `generated/Greeter.IceRpc.cs`
- [IceRpc.Deadline] and [IceRpc.Logger] - the packages with the two interceptors
we installed in our invocation pipeline

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ This command creates a new IceRPC server application in directory `MySliceServer

Let's examine each file:

### slice/Greeter.slice - the contract
### slice/VisitorCenter/Greeter.slice - the contract

This file holds the contract between our client and server applications,
specified with the [Slice] language.
Expand Down Expand Up @@ -181,6 +181,11 @@ await CancelKeyPressed;
await server.ShutdownAsync();
```

### Program.Authentication.cs - AuthenticationOptions helper

This file contains the `CreateServerAuthenticationOptions` helper method. It creates an
`SslServerAuthenticationOptions` from an `X509Certificate2`.

### Program.CancelKeyPressed.cs - small Ctrl+C helper

This file contains a few lines of code that `Program.cs` uses to wait for
Expand All @@ -193,7 +198,7 @@ NuGet packages:

- [IceRpc.Slice] - the IceRPC + Slice integration package
- [IceRpc.Slice.Tools] - the package that compiles `Greeter.slice` into
`generated/Greeter.IceRpc.cs`
`generated/Greeter.cs` and `generated/Greeter.IceRpc.cs`
- [IceRpc.Deadline] and [IceRpc.Logger] - the packages with the two middleware
we installed in the dispatch pipeline

Expand Down
2 changes: 1 addition & 1 deletion content/getting-started/installation/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dotnet new install IceRpc.Templates
## Using the templates

You use the IceRPC templates with the standard `dotnet new <template>` command. The following options are available
(note: `--transport` is supported by the IceRPC templates for Protobuf and Slice):
(note: `--transport` is supported by the non-DI IceRPC templates for Protobuf and Slice):

```
--no-restore If specified, skips the automatic restore of the project on create.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ but sequence type `MyClassLinkedList` uses the default mapping.
### Mapping to custom types

If the array mapping and the predefined containers are unsuitable for your application (for example, because you may
need a priority queue, which is not a standard C# container), you can implement your own custom containers and direct
need a specialized container such as a priority queue), you can implement your own custom containers and direct
the Ice compiler to map sequences to these custom containers. For example:

```ice
Expand Down
2 changes: 1 addition & 1 deletion content/icerpc-for-ice-users/rpc-core/object-adapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ await using var server = new Server(

server.Listen(); // similar to "activate"

await CancelKeyPressed;
await CancelKeyPressed; // a Task that completes on Ctrl+C
await server.ShutdownAsync();
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ code to help you use IceRPC with [Microsoft's DI container][microsoft-di-contain
All the DI-related APIs provided by IceRPC are in the same namespace, [IceRpc.Extensions.DependencyInjection], but are
implemented by several assemblies:

- [IceRpc.dll] provides abstractions such as [IDispatcherBuilder] and [IInvokerBuilder] [IceRpc.Deadline.dll] and other
interceptor/middleware assemblies provide extension methods for `IDispatcherBuilder` and `IInvokerBuilder`. These
extension methods are DI container agnostic.
- [IceRpc.dll] provides abstractions such as [IDispatcherBuilder] and [IInvokerBuilder].
- [IceRpc.Deadline.dll] and other interceptor/middleware assemblies provide extension methods for
`IDispatcherBuilder` and `IInvokerBuilder`. These extension methods are DI container agnostic.
- [IceRpc.Extensions.DependencyInjection.dll] provides support code for Microsoft's DI container. This includes various
extension methods for [IServiceCollection], such as [AddIceRpcServer] and [AddIceRpcClientConnection], and
implementations for `IDispatcherBuilder` and `IInvokerBuilder`.
Expand Down
2 changes: 1 addition & 1 deletion content/icerpc/slic-transport/protocol-frames.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ The parameters are used to configure the connection.

## Version frame

A `Version` frame carries a sequence of `varint62` values where each value specifies a Slic version. It is sent by a
A `Version` frame carries a sequence of `varuint62` values where each value specifies a Slic version. It is sent by a
server on connection establishment if the Slic version specified in the `Initialize` frame is not supported. It's defined
as follows:

Expand Down
1 change: 0 additions & 1 deletion content/slice/basics/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ module Example
interface WidgetFactory {
/// Creates a new {@link Widget}.
/// @param name: The name of the new widget.
/// @param color: The color of the new widget.
/// @returns: A proxy to the new widget.
createWidget(name: string) -> WidgetProxy

Expand Down
16 changes: 12 additions & 4 deletions content/slice/basics/slice-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,25 @@ Two files can also contain definitions with circular references, such as:
// in Chicken.slice
module Coop

interface Chicken {
Egg lay()
struct Chicken {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good fix. The previous example relied on proxy custom types (with the custom not shown), which was confusing.

name: string
}

interface Henhouse {
hatch(egg: Egg) -> Chicken
}
```

```slice
// in Egg.slice
module Coop

interface Egg {
Chicken hatch()
struct Egg {
weight: float64
}

interface Nest {
lay(chicken: Chicken) -> Egg
}
```

Expand Down
2 changes: 1 addition & 1 deletion content/slice/encoding/icerpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: Understand how the IceRPC + Slice integration applies the Slice enc
The IceRPC + Slice integration fills the payload of an [outgoing request] resp. [outgoing response] with the non-stream
arguments resp. return value (encoded into a segment).

It fills the payload continuation of an outgoing response (resp. outgoing request) with the encoded stream argument
It fills the payload continuation of an outgoing request (resp. outgoing response) with the encoded stream argument
resp. stream return value, if any.

## Custom type ServiceAddress {% icerpcSlice=true %}
Expand Down
5 changes: 3 additions & 2 deletions content/slice/encoding/primitive-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ encode a value on more bytes than required, and a Slice decoder must always deco
`7` is usually encoded on a single byte but can also be encoded on 2, 4 or 8 bytes.

{% callout type="note" %}
The encoding of varuint62 is identical to the encoding of variable-length integers in QUIC, except for the byte order
(QUIC is big-endian, Slice is little-endian).
The encoding of varuint62 is similar to the encoding of variable-length integers in QUIC, with two differences: QUIC
stores the 2-bit length in the most significant bits of the first byte and uses big-endian ordering, while Slice stores
this length in the least significant bits of the first byte and uses little-endian ordering.
{% /callout %}

## Floating-point types
Expand Down
2 changes: 1 addition & 1 deletion content/slice/encoding/user-defined-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ The contact id = 5, name = not set, age = 42 is encoded as:
- empty bit sequence since no non-tagged field has an optional type
0x05 0x00 0x00 0x00: id (5 on 4 bytes, little-endian)
- nothing for the name since it's not set
0x10: age's tag (2 as a varint32 on 1 byte)
0x08: age's tag (2 as a varint32 on 1 byte)
0x04: age's value size (1 as a varuint62 on 1 byte)
0x2A: age's encoded value on a single byte
0xFC: tag end marker (-1 varint32, encoded on 1 byte)
Expand Down
6 changes: 4 additions & 2 deletions content/slice/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ Slice provides a readable, modern syntax inspired by Rust and Swift. It includes
the `stream` keyword, allows you to turn any type into an optional type with the `?` suffix, requires minimal
punctuation, and more.

The Slice [primitive] types have clear names such as `uint8`, `float64`, and `string`. Slice also includes two built-in
generic types, [Sequence] and [Dictionary]. And Slice lets you define your own types with [custom], [enum], and [struct].
The Slice [primitive] types have clear names such as `uint8`, `float64`, and `string`. Slice also includes three
built-in generic types: [Sequence], [Dictionary], and [Result]. And Slice lets you define your own types with [custom],
[enum], and [struct].

Last but not least, Slice's [tagged] fields and parameters allow you to update your structs and operations over time
without breaking on-the-wire compatibility.
Expand Down Expand Up @@ -161,6 +162,7 @@ decode instances of your custom type.
[Interface Definition Language]: https://en.wikipedia.org/wiki/Interface_description_language
[IFeatureCollection]: csharp:IceRpc.Features.IFeatureCollection
[primitive]: /slice/language-guide/primitive-types
[Result]: /slice/language-guide/result-types
[Sequence]: /slice/language-guide/sequence-types
[struct]: /slice/language-guide/struct-types
[tagged]: /slice/language-guide/fields#tagged-fields
2 changes: 1 addition & 1 deletion content/slice/language-guide/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ The following attributes are specific to the C# mapping. They all start with the
| Attribute | Applies to | Description |
| --------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [`cs::attribute`][cs-attribute-attribute] | Enum types, enumerators, variants, and fields | Add the specified C# attribute to the mapped C# enum, enumerator, variant, or field. |
| [`cs::encodeReturn`][cs-encoded-return] | Operations | Return an already encoded return value (server-side only). |
| [`cs::encodedReturn`][cs-encoded-return] | Operations | Return an already encoded return value (server-side only). |
| [`cs::identifier`](#cs::identifier-attribute) | Modules, interfaces, operations, parameters, user-defined types, fields, enumerators, and variants | Change the name of the mapped C# identifier. |
| [`cs::public`](#cs::public-attribute) | Interfaces and user-defined types | Map to a public C# type instead of an internal C# type. |
| [`cs::readonly`][cs-readonly] | Structs and struct fields | Adds `readonly` to the mapped C# struct or field. |
Expand Down
9 changes: 4 additions & 5 deletions content/slice/language-guide/comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface FooBar { // This is another comment
}
```

Slice also supports block comments (`/* ... */`), like C, including nested block comments.
Slice also supports block comments (`/* ... */`), like C. Block comments cannot be nested.

The Slice compiler completely ignores comments that are not doc comments.

Expand Down Expand Up @@ -47,14 +47,13 @@ module Example
interface WidgetFactory {
/// Creates a new {@link Widget}.
/// @param name: The name of the new widget.
/// @param color: The color of the new widget.
/// @returns: A proxy to the new widget.
/// @returns: The new widget.
createWidget(name: string) -> Widget

/// Retrieves the last {@link Widget} created by this factory.
/// @returns proxy: A proxy to the last widget.
/// @returns widget: A copy of the last widget.
/// @returns timeStamp: The creation time stamp.
getLastWidget() -> (proxy: Widget, timeStamp: WellKnownTypes::TimeStamp)
getLastWidget() -> (widget: Proxy, timeStamp: WellKnownTypes::TimeStamp)
}
```

4 changes: 2 additions & 2 deletions content/slice/language-guide/dictionary-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ the same Slice type, and all values have the same Slice type.
A dictionary is like a sequence of key-value pairs with the following constraints:

- each key is unique
- the type of the key is a string, bool, integral type, enum type, custom type, or a compact struct with key-compatible
fields
- the type of the key is a string, bool, integral type, basic enum type, custom type, or a compact struct with
key-compatible fields

You can construct a dictionary type inline, without giving it a name, for example to specify the type of a parameter or
field:
Expand Down
4 changes: 2 additions & 2 deletions content/slice/language-guide/interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ All operations are abstract at the Slice level: you can't implement an operation

When you create an application with Slice, these interfaces are your entry point into Slice: the Slice code generators
generate code from your Slice interfaces, and you interact with this generated code in both your client and server
applications. On the client side, you call generated proxies (concrete classes) that send requests to remote services.
applications. On the client side, you call generated proxies (concrete types) that send requests to remote services.
On the server side, you implement services using templates (abstract interfaces) generated from the Slice interfaces.

{% callout %}
Expand Down Expand Up @@ -168,7 +168,7 @@ available as the constant `DefaultServicePath` in the generated proxy struct:
```csharp
internal readonly partial record struct WidgetProxy : IWidget, IProxy
{
internal const string DefaultServicePath = "/Example/Widget";
internal const string DefaultServicePath = "/Example.Widget";
}
```

Expand Down
4 changes: 2 additions & 2 deletions content/slice/language-guide/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ description: Learn about Slice modules.

## Module basics

A module is a naming scope for Slice types. It allows you to define and reference different Slice types with the same
name, provided they are in different scopes (modules).
A module is a naming scope for Slice types and interfaces. It allows you to define and reference different Slice types
and interfaces with the same name, provided they are in different scopes (modules).

Slice uses `::` as its [scope resolution operator][scope-resolution-operator].

Expand Down
4 changes: 2 additions & 2 deletions content/slice/language-guide/operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ code for their payloads.

### cs::encodedReturn attribute

The `cs::encodeReturn` attribute allows you to change the return type of the mapped method on the generated Service
interface: this attribute makes this method returns a `ValueTask<PipeReader>` instead of the usual `ValueTask<T>`.
The `cs::encodedReturn` attribute allows you to change the return type of the mapped method on the generated Service
interface: this attribute makes the method return a `ValueTask<PipeReader>` instead of the usual `ValueTask<T>`.

The returned [PipeReader] represents the encoded return value. You would typically produce this value using
the Encode*OpName* method provided by the helper [`Response` class](#request-and-response-helper-classes).
Expand Down
2 changes: 1 addition & 1 deletion content/slice/language-guide/sequence-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ attribute accepts a single string argument: the name of a type similar to `List<

More specifically, this type must:

- provide a constructor that accepts an `IEnumerable<T>` or a `T[]` when T is a bool or a fixed-size integral type
- provide a constructor that accepts an `IEnumerable<T>` or a `T[]` when T is a fixed-size primitive type
- provide a capacity constructor (with an `int` parameter) otherwise

This type must implement `IList<T>` when `cs::type` is applied to a field; it must implement `ICollection<T>` when
Expand Down
4 changes: 0 additions & 4 deletions content/slice/language-reference/doc-comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ DocComment
: Overview?
| DocComment ParamBlock
| DocComment ReturnsBlock
| DocComment ThrowsBlock
| DocComment SeeBlock
;

Expand All @@ -49,9 +48,6 @@ ReturnsBlock
: returns_keyword identifier? Section
;

ThrowsBlock
: throws_keyword identifier Section
;

SeeBlock
: see_keyword ScopedIdentifier newline
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ identifier: LETTER ALPHANUMERIC*;

// Directive keywords
define_keyword: "#" "define";
undefined_keyword: "#" "undef";
undefine_keyword: "#" "undef";
if_keyword: "#" "if";
elif_keyword: "#" "elif";
else_keyword: "#" "else";
Expand Down
Loading