This commit is contained in:
Orion Kindel 2023-04-20 01:58:43 -05:00
parent c4bd8c6273
commit b8e9eaceb0
Signed by untrusted user who does not match committer: orion
GPG Key ID: 6D4165AE4C928719
11 changed files with 103 additions and 47 deletions

View File

@ -1,8 +1,8 @@
package dev.toad;
import dev.toad.msg.Code;
import dev.toad.msg.Type;
import dev.toad.msg.Message;
import dev.toad.msg.Type;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.Optional;
@ -16,12 +16,16 @@ public final class Client implements AutoCloseable {
this.toad = toad;
}
public CompletableFuture<Message> get(String uri) throws URISyntaxException, UnknownHostException {
public CompletableFuture<Message> get(String uri)
throws URISyntaxException, UnknownHostException {
return this.get(Type.CON, uri);
}
public CompletableFuture<Message> get(Type ty, String uri) throws URISyntaxException, UnknownHostException {
return this.send(Message.builder().uri(uri).type(ty).code(Code.GET).build());
public CompletableFuture<Message> get(Type ty, String uri)
throws URISyntaxException, UnknownHostException {
return this.send(
Message.builder().uri(uri).type(ty).code(Code.GET).build()
);
}
public CompletableFuture<Message> send(Message message) {

View File

@ -2,8 +2,8 @@ package dev.toad.msg;
import dev.toad.msg.option.Accept;
import dev.toad.msg.option.ContentFormat;
import dev.toad.msg.option.Path;
import dev.toad.msg.option.Host;
import dev.toad.msg.option.Path;
import dev.toad.msg.option.Query;
import java.net.InetSocketAddress;
import java.util.List;
@ -34,27 +34,27 @@ public interface Message {
public byte[] toBytes();
default public Optional<Option> getOption(long number) {
public default Optional<Option> getOption(long number) {
return this.options().stream().filter(o -> o.number() == number).findAny();
}
default public Optional<Accept> getAccept() {
public default Optional<Accept> getAccept() {
return this.getOption(Accept.number).map(o -> new Accept(o));
}
default public Optional<ContentFormat> getContentFormat() {
public default Optional<ContentFormat> getContentFormat() {
return this.getOption(ContentFormat.number).map(o -> new ContentFormat(o));
}
default public Optional<Path> getPath() {
public default Optional<Path> getPath() {
return this.getOption(Path.number).map(o -> new Path(o));
}
default public Optional<Host> getHost() {
public default Optional<Host> getHost() {
return this.getOption(Host.number).map(o -> new Host(o));
}
default public Optional<Query> getQuery() {
public default Optional<Query> getQuery() {
return this.getOption(Query.number).map(o -> new Query(o));
}
}

View File

@ -1,10 +1,11 @@
package dev.toad.msg;
import java.util.Optional;
import dev.toad.msg.option.ContentFormat;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
public final class Payload {
final byte[] bytes;
final Optional<ContentFormat> contentFormat;

View File

@ -1,18 +1,18 @@
package dev.toad.msg.build;
import dev.toad.msg.Payload;
import dev.toad.msg.Code;
import dev.toad.msg.Id;
import dev.toad.msg.Payload;
import dev.toad.msg.Token;
import dev.toad.msg.Type;
import dev.toad.msg.option.Host;
import dev.toad.msg.option.Path;
import dev.toad.msg.option.Query;
import dev.toad.msg.option.Host;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.net.URI;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -38,14 +38,16 @@ public final class Message
return new Message();
}
public MessageNeeds.Type uri(String uriStr) throws URISyntaxException, UnknownHostException {
public MessageNeeds.Type uri(String uriStr)
throws URISyntaxException, UnknownHostException {
var uri = new URI(uriStr);
var addr = InetAddress.getByName(uri.getHost());
var port = uri.getPort() > 0 ? uri.getPort() : uri.getScheme().equals("coaps") ? 5684 : 5683;
var port = uri.getPort() > 0
? uri.getPort()
: uri.getScheme().equals("coaps") ? 5684 : 5683;
this.addr = Optional.of(new InetSocketAddress(addr, port));
return this
.option(new Host(uri.getHost()))
return this.option(new Host(uri.getHost()))
.option(new Query(uri.getQuery()))
.option(new Path(uri.getPath()));
}
@ -108,7 +110,7 @@ public final class Message
this.code.get(),
this.id.orElse(Id.defaultId()),
this.token.orElse(Token.defaultToken()),
this.payload.map(p -> p.bytes()).orElse(new byte[]{}),
this.payload.map(p -> p.bytes()).orElse(new byte[] {}),
this.options.entrySet()
.stream()
.map(ent -> new dev.toad.msg.owned.Option(ent.getKey(), ent.getValue()))

View File

@ -1,13 +1,14 @@
package dev.toad.msg.build;
import java.net.InetSocketAddress;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.net.InetSocketAddress;
public final class MessageNeeds {
public interface Destination {
MessageNeeds.Type uri(String uri) throws URISyntaxException, UnknownHostException;
MessageNeeds.Type uri(String uri)
throws URISyntaxException, UnknownHostException;
MessageNeeds.Type addr(InetSocketAddress addr);
}

View File

@ -1,13 +1,13 @@
package dev.toad.msg.option;
import java.util.Arrays;
import java.util.stream.Collectors;
import dev.toad.ffi.u16;
import dev.toad.msg.Option;
import dev.toad.msg.OptionValue;
import java.util.ArrayList;
import java.util.List;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public sealed class ContentFormat implements Option permits Accept {
@ -17,11 +17,22 @@ public sealed class ContentFormat implements Option permits Accept {
public ContentFormat(Option o) {
if (o.number() != ContentFormat.number) {
throw new IllegalArgumentException(String.format("%d != ContentFormat number %d", o.number(), Path.number));
throw new IllegalArgumentException(
String.format("%d != ContentFormat number %d", o.number(), Path.number)
);
}
if (o.values().size() > 1) {
throw new IllegalArgumentException(String.format("ContentFormat is not repeatable, %s", o.values().stream().map(v -> v.asString()).collect(Collectors.toList())));
throw new IllegalArgumentException(
String.format(
"ContentFormat is not repeatable, %s",
o
.values()
.stream()
.map(v -> v.asString())
.collect(Collectors.toList())
)
);
}
var bytes = o.values().get(0).asBytes();
@ -32,7 +43,7 @@ public sealed class ContentFormat implements Option permits Accept {
} else if (bytes.length == 2) {
this.value = new u16(buf.getShort());
} else if (bytes.length == 3) {
buf.put(0, (byte)0);
buf.put(0, (byte) 0);
this.value = new u16(buf.getInt());
} else {
this.value = new u16(buf.getInt());

View File

@ -3,22 +3,34 @@ package dev.toad.msg.option;
import dev.toad.msg.Option;
import dev.toad.msg.OptionValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public final class Host implements Option {
final String host;
public static final long number = 3;
public Host(Option o) {
if (o.number() != Host.number) {
throw new IllegalArgumentException(String.format("%d != Host number %d", o.number(), Path.number));
throw new IllegalArgumentException(
String.format("%d != Host number %d", o.number(), Path.number)
);
}
if (o.values().size() > 1) {
throw new IllegalArgumentException(String.format("Host is not repeatable, %s", o.values().stream().map(v -> v.asString()).collect(Collectors.toList())));
throw new IllegalArgumentException(
String.format(
"Host is not repeatable, %s",
o
.values()
.stream()
.map(v -> v.asString())
.collect(Collectors.toList())
)
);
}
this.host = o.values().get(0).asString();
@ -40,7 +52,7 @@ public final class Host implements Option {
@Override
public boolean equals(Object other) {
return switch(other) {
return switch (other) {
case Host h -> this.toString().equals(h.toString());
default -> false;
};

View File

@ -3,21 +3,29 @@ package dev.toad.msg.option;
import dev.toad.msg.Option;
import dev.toad.msg.OptionValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public final class Path implements Option {
final ArrayList<String> segments;
public static final long number = 11;
public Path(Option o) {
if (o.number() != Path.number) {
throw new IllegalArgumentException(String.format("%d != Path number %d", o.number(), Path.number));
throw new IllegalArgumentException(
String.format("%d != Path number %d", o.number(), Path.number)
);
}
this.segments = o.values().stream().map(v -> v.asString()).collect(Collectors.toCollection(() -> new ArrayList<>()));
this.segments =
o
.values()
.stream()
.map(v -> v.asString())
.collect(Collectors.toCollection(() -> new ArrayList<>()));
}
public Path(String path) {
@ -52,6 +60,8 @@ public final class Path implements Option {
@Override
public List<OptionValue> values() {
return this.segments.stream().map(s -> new dev.toad.msg.owned.OptionValue(s)).collect(Collectors.toList());
return this.segments.stream()
.map(s -> new dev.toad.msg.owned.OptionValue(s))
.collect(Collectors.toList());
}
}

View File

@ -2,12 +2,12 @@ package dev.toad.msg.option;
import dev.toad.msg.Option;
import dev.toad.msg.OptionValue;
import java.util.Optional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -20,10 +20,17 @@ public final class Query implements Option {
public Query(Option o) {
if (o.number() != Query.number) {
throw new IllegalArgumentException(String.format("%d != Query number %d", o.number(), Query.number));
throw new IllegalArgumentException(
String.format("%d != Query number %d", o.number(), Query.number)
);
}
this.query = o.values().stream().map(v -> v.asString()).collect(Collectors.toCollection(() -> new ArrayList<>()));
this.query =
o
.values()
.stream()
.map(v -> v.asString())
.collect(Collectors.toCollection(() -> new ArrayList<>()));
}
public Query(String query) {
@ -79,6 +86,7 @@ public final class Query implements Option {
}
public static final class Value {
final Optional<String> val;
public Value(String val) {
@ -100,7 +108,7 @@ public final class Query implements Option {
@Override
public String toString() {
if (!this.value().isEmpty()) {
return "Query.Value(\""+this.value().get()+"\")";
return "Query.Value(\"" + this.value().get() + "\")";
} else {
return "Query.Value.empty()";
}
@ -112,7 +120,7 @@ public final class Query implements Option {
@Override
public boolean equals(Object other) {
return switch(other) {
return switch (other) {
case Value v -> this.equals(v);
default -> false;
};

View File

@ -81,7 +81,10 @@ class MessageBuilder extends munit.FunSuite {
.code(Code.GET)
.build
assertEquals(Seq.from(msg.getPath.get.segments.asScala), Seq("cheese", "gruyere"))
assertEquals(
Seq.from(msg.getPath.get.segments.asScala),
Seq("cheese", "gruyere")
)
}
test("uri sets query to query section of uri") {

View File

@ -41,8 +41,12 @@ class Options extends munit.FunSuite {
),
Map(
"foo" -> Seq(Query.Value("test")),
"bar" -> Seq(Query.Value.empty, Query.Value.empty, Query.Value("third")),
"quux" -> Seq(Query.Value("a"), Query.Value("b")),
"bar" -> Seq(
Query.Value.empty,
Query.Value.empty,
Query.Value("third")
),
"quux" -> Seq(Query.Value("a"), Query.Value("b"))
)
)
}