From 66535e11cef5dfb3d2d444bc2678616a5d1e619e Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 13 Mar 2025 17:24:20 -0400 Subject: [PATCH] - Removes the TAG_SIZE constant on all tags because each parser might use a different size. There is no minimum size for tags. - Moves the tag parsing checks to use ensure. - Explicitly writes matching methods to avoid hiding complexity beyond utility functions. --- .../audio/header/tags/DownloadUrlTag.kt | 8 ++- .../audio/header/tags/StreamUrlTag.kt | 8 ++- .../audio/header/tags/WaveformTag.kt | 8 ++- .../experimental/audio/track/tags/CoverTag.kt | 8 ++- .../experimental/audio/track/tags/MediaTag.kt | 8 ++- .../audio/track/tags/ParticipantTag.kt | 16 ++--- .../experimental/audio/track/tags/PriceTag.kt | 8 ++- .../experimental/audio/track/tags/TypeTag.kt | 8 ++- .../quartz/experimental/bounties/RewardTag.kt | 7 ++- .../experimental/forks/MarkedETagExt.kt | 2 +- .../interactiveStories/tags/ReadStatusTag.kt | 8 ++- .../interactiveStories/tags/RootSceneTag.kt | 1 - .../interactiveStories/tags/StoryOptionTag.kt | 1 - .../quartz/experimental/nns/tags/IPv4Tag.kt | 8 ++- .../quartz/experimental/nns/tags/IPv6Tag.kt | 8 ++- .../experimental/nns/tags/VersionTag.kt | 8 ++- .../relationshipStatus/tags/PetnameTag.kt | 8 ++- .../relationshipStatus/tags/RankTag.kt | 8 ++- .../relationshipStatus/tags/SummaryTag.kt | 8 ++- .../experimental/zapPolls/tags/ClosedAtTag.kt | 8 ++- .../zapPolls/tags/ConsensusThresholdTag.kt | 7 ++- .../experimental/zapPolls/tags/MaximumTag.kt | 8 ++- .../experimental/zapPolls/tags/MinimumTag.kt | 8 ++- .../zapPolls/tags/PollOptionTag.kt | 9 ++- .../quartz/nip01Core/core/Tag.kt | 58 +------------------ .../quartz/nip01Core/core/TagArrayBuilder.kt | 16 +---- .../nip01Core/tags/addressables/ATag.kt | 23 ++++---- .../quartz/nip01Core/tags/events/ETag.kt | 20 +++++-- .../nip01Core/tags/hashtags/HashtagTag.kt | 10 +++- .../quartz/nip01Core/tags/kinds/KindTag.kt | 14 +++-- .../quartz/nip01Core/tags/people/PTag.kt | 20 ++++--- .../nip01Core/tags/references/ReferenceTag.kt | 14 +++-- .../quartz/nip02FollowList/tags/ContactTag.kt | 26 ++++++--- .../quartz/nip10Notes/tags/MarkedETag.kt | 9 ++- .../quartz/nip10Notes/tags/Positional.kt | 6 +- .../quartz/nip13Pow/tags/PoWTag.kt | 13 +++-- .../quartz/nip14Subject/SubjectTag.kt | 10 +++- .../nip17Dm/files/tags/EncryptionAlgo.kt | 10 +++- .../nip17Dm/files/tags/EncryptionKey.kt | 9 ++- .../nip17Dm/files/tags/EncryptionNonce.kt | 9 ++- .../quartz/nip17Dm/files/tags/FileTypeTag.kt | 10 +++- .../nip18Reposts/quotes/QAddressableTag.kt | 10 ++-- .../quartz/nip18Reposts/quotes/QEventTag.kt | 10 +++- .../quartz/nip18Reposts/quotes/QTag.kt | 23 ++++++-- .../quartz/nip22Comments/CommentEvent.kt | 4 +- .../nip22Comments/tags/ReplyAddressTag.kt | 23 +++++--- .../nip22Comments/tags/ReplyAuthorTag.kt | 21 ++++--- .../nip22Comments/tags/ReplyEventTag.kt | 34 +++++++---- .../nip22Comments/tags/ReplyIdentifierTag.kt | 14 +++-- .../quartz/nip22Comments/tags/ReplyKindTag.kt | 22 +++---- .../nip22Comments/tags/RootAddressTag.kt | 25 +++++--- .../nip22Comments/tags/RootAuthorTag.kt | 20 +++---- .../quartz/nip22Comments/tags/RootEventTag.kt | 34 +++++++---- .../nip22Comments/tags/RootIdentifierTag.kt | 14 +++-- .../quartz/nip22Comments/tags/RootKindTag.kt | 14 +++-- .../quartz/nip23LongContent/tags/ImageTag.kt | 8 ++- .../nip23LongContent/tags/PublishedAtTag.kt | 8 ++- .../nip23LongContent/tags/SummaryTag.kt | 8 ++- .../quartz/nip23LongContent/tags/TitleTag.kt | 8 ++- .../vitorpamplona/quartz/nip31Alts/AltTag.kt | 10 +++- .../nip34Git/repository/tags/CloneTag.kt | 8 ++- .../repository/tags/DescriptionTag.kt | 8 ++- .../nip34Git/repository/tags/NameTag.kt | 8 ++- .../quartz/nip34Git/repository/tags/WebTag.kt | 8 ++- .../quartz/nip35Torrents/tags/BtihTag.kt | 8 ++- .../quartz/nip35Torrents/tags/FileTag.kt | 13 +++-- .../quartz/nip35Torrents/tags/InfoHashTag.kt | 8 ++- .../quartz/nip35Torrents/tags/TrackerTag.kt | 8 ++- .../streaming/tags/CurrentParticipantsTag.kt | 8 ++- .../streaming/tags/EndsTag.kt | 8 ++- .../streaming/tags/ParticipantTag.kt | 34 ++++++----- .../streaming/tags/RelayListTag.kt | 8 ++- .../streaming/tags/StartsTag.kt | 8 ++- .../streaming/tags/StatusTag.kt | 8 ++- .../streaming/tags/StreamingTag.kt | 8 ++- .../streaming/tags/TotalParticipantsTag.kt | 8 ++- .../nip57Zaps/zapraiser/ZapRaiserTag.kt | 2 +- .../quartz/nip71Video/tags/DurationTag.kt | 8 ++- .../quartz/nip71Video/tags/SegmentTag.kt | 9 ++- .../quartz/nip71Video/tags/TextTrackTag.kt | 7 ++- .../definition/tags/DescriptionTag.kt | 8 ++- .../definition/tags/ImageTag.kt | 8 ++- .../definition/tags/ModeratorTag.kt | 14 +++-- .../definition/tags/NameTag.kt | 8 ++- .../definition/tags/RelayTag.kt | 7 ++- .../definition/tags/RulesTag.kt | 8 ++- .../quartz/nip75ZapGoals/tags/AmountTag.kt | 8 ++- .../quartz/nip75ZapGoals/tags/ClosedAtTag.kt | 8 ++- .../quartz/nip75ZapGoals/tags/RelayListTag.kt | 8 ++- .../quartz/nip84Highlights/tags/ContextTag.kt | 8 ++- .../definition/tags/PlatformLinkTag.kt | 9 +-- .../recommendation/AppRecommendationEvent.kt | 2 +- .../recommendation/tags/RecommendationTag.kt | 12 ++-- .../quartz/nip92IMeta/IMetaTag.kt | 8 ++- .../nip94FileMetadata/tags/BlurhashTag.kt | 8 ++- .../nip94FileMetadata/tags/DimensionTag.kt | 8 ++- .../nip94FileMetadata/tags/FallbackTag.kt | 8 ++- .../nip94FileMetadata/tags/HashSha256Tag.kt | 8 ++- .../quartz/nip94FileMetadata/tags/ImageTag.kt | 7 ++- .../nip94FileMetadata/tags/MagnetTag.kt | 8 ++- .../nip94FileMetadata/tags/MimeTypeTag.kt | 10 +++- .../nip94FileMetadata/tags/OriginalHashTag.kt | 8 ++- .../nip94FileMetadata/tags/ServiceTag.kt | 10 +++- .../quartz/nip94FileMetadata/tags/SizeTag.kt | 8 ++- .../nip94FileMetadata/tags/SummaryTag.kt | 10 +++- .../quartz/nip94FileMetadata/tags/ThumbTag.kt | 7 ++- .../nip94FileMetadata/tags/TorrentInfoHash.kt | 8 ++- .../quartz/nip94FileMetadata/tags/UrlTag.kt | 10 +++- .../nip96FileStorage/config/tags/ServerTag.kt | 8 ++- .../quartz/nip98HttpAuth/tags/MethodTag.kt | 8 ++- .../nip98HttpAuth/tags/PayloadHashTag.kt | 7 ++- .../quartz/nip98HttpAuth/tags/UrlTag.kt | 8 ++- .../nip99Classifieds/tags/ConditionTag.kt | 8 ++- .../nip99Classifieds/tags/LocationTag.kt | 8 ++- .../quartz/nip99Classifieds/tags/PriceTag.kt | 7 ++- .../quartz/nip99Classifieds/tags/StatusTag.kt | 8 ++- 116 files changed, 807 insertions(+), 440 deletions(-) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt index 5f335b67b..6e69131b7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/DownloadUrlTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.header.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class DownloadUrlTag { companion object { const val TAG_NAME = "download_url" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt index d3bc35de7..2e896aa98 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/StreamUrlTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.header.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class StreamUrlTag { companion object { const val TAG_NAME = "stream_url" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt index 0942299f2..491653632 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/header/tags/WaveformTag.kt @@ -21,7 +21,9 @@ package com.vitorpamplona.quartz.experimental.audio.header.tags import com.fasterxml.jackson.module.kotlin.readValue +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.jackson.EventMapper +import com.vitorpamplona.quartz.utils.ensure class WaveformTag( val wave: List, @@ -30,12 +32,12 @@ class WaveformTag( companion object { const val TAG_NAME = "waveform" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): WaveformTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } val wave = runCatching { EventMapper.mapper.readValue>(tag[1]) }.getOrNull() if (wave.isNullOrEmpty()) return null return WaveformTag(wave) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt index e52b81d2e..56488bb95 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/CoverTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.track.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class CoverTag { companion object { const val TAG_NAME = "cover" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt index d620dbe45..7ebaacc27 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/MediaTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.track.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MediaTag { companion object { const val TAG_NAME = "media" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt index 1701e908f..ebc074a71 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/ParticipantTag.kt @@ -23,9 +23,10 @@ package com.vitorpamplona.quartz.experimental.audio.track.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.isNotName +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable data class ParticipantTag( @@ -36,26 +37,27 @@ data class ParticipantTag( companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Tag): ParticipantTag? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ParticipantTag(tag[1], tag.getOrNull(2)) } @JvmStatic fun parseKey(tag: Tag): String? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } @JvmStatic fun assemble( pubkey: HexKey, - relayHint: String?, + relayHint: String? = null, ) = arrayOfNotNull(TAG_NAME, pubkey, relayHint) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt index c0439e8df..dde2c19ae 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/PriceTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.track.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class PriceTag { companion object { const val TAG_NAME = "price" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt index fd3a227c6..34bf125a3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/audio/track/tags/TypeTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.audio.track.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class TypeTag { companion object { const val TAG_NAME = "c" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt index e8f3acd97..cb514b1d7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/bounties/RewardTag.kt @@ -20,16 +20,19 @@ */ package com.vitorpamplona.quartz.experimental.bounties +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure import java.math.BigDecimal class RewardTag { companion object { const val TAG_NAME = "reward" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): BigDecimal? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return runCatching { BigDecimal(tag[1]) }.getOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt index 9a3217b0e..fa1a7b02e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/forks/MarkedETagExt.kt @@ -24,7 +24,7 @@ import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag.MARKER fun MarkedETag.Companion.parseFork(tag: Array): MarkedETag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + if (tag.size < 4 || tag[0] != "e") return null if (tag[ORDER_MARKER] != MARKER.FORK.code) return null // ["e", id hex, relay hint, marker, pubkey] return MarkedETag( diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt index c09d4e768..28a5eaf8d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/ReadStatusTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.experimental.interactiveStories.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ReadStatusTag { enum class STATUS( val value: String, @@ -34,11 +37,12 @@ class ReadStatusTag { companion object { const val TAG_NAME = "status" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt index 01062321e..ae354c2d0 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/RootSceneTag.kt @@ -60,7 +60,6 @@ data class RootSceneTag( companion object { const val TAG_NAME = "A" - const val TAG_SIZE = 2 fun assembleATagId( kind: Int, diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt index 652e68129..a17697642 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/interactiveStories/tags/StoryOptionTag.kt @@ -35,7 +35,6 @@ class StoryOptionTag( companion object { const val TAG_NAME = "option" - const val TAG_SIZE = 3 @JvmStatic fun parse(tag: Array): StoryOptionTag? { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt index c8f7ded13..f6b2024f3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv4Tag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.nns.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class IPv4Tag { companion object { const val TAG_NAME = "ip4" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt index 07086b274..db673d7db 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/IPv6Tag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.nns.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class IPv6Tag { companion object { const val TAG_NAME = "ip6" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt index 2eca2f76c..7de43e61d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/nns/tags/VersionTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.nns.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class VersionTag { companion object { const val TAG_NAME = "version" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetnameTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetnameTag.kt index df1ccfbfc..ea9b4981a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetnameTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/PetnameTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.relationshipStatus.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class PetnameTag { companion object { const val TAG_NAME = "petname" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt index 3525445d0..b39bce3ae 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/RankTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.relationshipStatus.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class RankTag { companion object { const val TAG_NAME = "rank" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt index 8a7696c29..058c58a74 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/relationshipStatus/tags/SummaryTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.relationshipStatus.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class SummaryTag { companion object { const val TAG_NAME = "summary" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt index 5b07019a8..21883f052 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ClosedAtTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.zapPolls.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ClosedAtTag { companion object { const val TAG_NAME = "closed_at" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt index 87e3967ec..b1d2fce00 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/ConsensusThresholdTag.kt @@ -20,16 +20,19 @@ */ package com.vitorpamplona.quartz.experimental.zapPolls.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure import kotlin.math.round class ConsensusThresholdTag { companion object { const val TAG_NAME = "consensus_threshold" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Double? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull()?.toDouble()?.div(100) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt index bf6381dee..286c9876d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MaximumTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.zapPolls.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MaximumTag { companion object { const val TAG_NAME = "value_maximum" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt index 7f1b8cfe8..5a1fb5ed8 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/MinimumTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.experimental.zapPolls.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MinimumTag { companion object { const val TAG_NAME = "value_minimum" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt index f5a74b06d..1ab922f5f 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/experimental/zapPolls/tags/PollOptionTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.experimental.zapPolls.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class PollOptionTag( val index: Int, val descriptor: String, @@ -28,11 +31,13 @@ class PollOptionTag( companion object { const val TAG_NAME = "poll_option" - const val TAG_SIZE = 3 @JvmStatic fun parse(tag: Array): PollOptionTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + ensure(tag[2].isNotEmpty()) { return null } val index = tag[1].toIntOrNull() ?: return null diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt index d97acc9c1..d9273988a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/Tag.kt @@ -27,64 +27,12 @@ typealias Tag = Array */ fun Tag.has(index: Int) = size > index -/** - * Returns if the Tag has less than $index elements. - */ -fun Tag.lacks(index: Int) = size <= index - fun Tag.name() = this[0] fun Tag.value() = this[1] -fun Tag.hasValue() = this[1].isNotEmpty() +fun Tag.hasValue() = if (has(1)) this[1].isNotEmpty() else false -fun Tag.nameOrNull() = if (size > 0) name() else null +fun Tag.nameOrNull() = if (has(0)) this[0] else null -fun Tag.valueOrNull() = if (size > 1) value() else null - -fun Tag.isNameUnsafe(name: String): Boolean = name() == name - -fun Tag.isValueUnsafe(value: String): Boolean = value() == value - -fun Tag.isValueInUnsafe(values: Set): Boolean = value() in values - -fun Tag.match(name: String): Boolean = if (size > 0) isNameUnsafe(name) else false - -fun Tag.isValue(value: String): Boolean = if (size > 1) isValueUnsafe(value) else false - -fun Tag.match( - name: String, - value: String, - minSize: Int, -): Boolean = if (size >= minSize) isNameUnsafe(name) && isValueUnsafe(value) else false - -fun Tag.match( - name: String, - values: Set, - minSize: Int, -): Boolean = if (size >= minSize) isNameUnsafe(name) && isValueInUnsafe(values) else false - -fun Tag.match( - name: String, - minSize: Int, -): Boolean = if (size >= minSize) isNameUnsafe(name) else false - -fun Tag.isNotName( - name: String, - minSize: Int, -): Boolean = !match(name, minSize) - -fun Tag.matchAndHasValue( - name: String, - minSize: Int, -): Boolean = if (size >= minSize) isNameUnsafe(name) && hasValue() else false - -fun Tag.valueIfMatches( - name: String, - minSize: Int, -): String? = if (match(name, minSize)) value() else null - -fun Tag.valueToIntIfMatches( - name: String, - minSize: Int, -): Int? = if (match(name, minSize)) value().toIntOrNull() else null +fun Tag.valueOrNull() = if (has(1)) this[1] else null diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt index 3d03f667b..aab802bed 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/core/TagArrayBuilder.kt @@ -35,7 +35,7 @@ class TagArrayBuilder { tagName: String, tagValue: String, ): TagArrayBuilder { - tagList[tagName]?.removeIf { it.value() == tagValue } + tagList[tagName]?.removeIf { it.valueOrNull() == tagValue } if (tagList[tagName]?.isEmpty() == true) { tagList.remove(tagName) } @@ -46,18 +46,8 @@ class TagArrayBuilder { predicate: (Tag, Tag) -> Boolean, toCompare: Tag, ): TagArrayBuilder { - tagList[toCompare.name()]?.removeIf { predicate(it, toCompare) } - if (tagList[toCompare.name()]?.isEmpty() == true) { - tagList.remove(toCompare.name()) - } - return this - } - - fun removeIf( - tagName: String, - tagValue: String, - ): TagArrayBuilder { - tagList[tagName]?.removeIf { it.value() == tagValue } + val tagName = toCompare.nameOrNull() ?: return this + tagList[tagName]?.removeIf { predicate(it, toCompare) } if (tagList[tagName]?.isEmpty() == true) { tagList.remove(tagName) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt index 2f8e464d1..07ba6ac59 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/addressables/ATag.kt @@ -23,9 +23,6 @@ package com.vitorpamplona.quartz.nip01Core.tags.addressables import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.has -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.name -import com.vitorpamplona.quartz.nip01Core.core.value import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory @@ -57,40 +54,44 @@ data class ATag( companion object { const val TAG_NAME = "a" - const val TAG_SIZE = 2 @JvmStatic - fun isTagged(tag: Array) = tag.size >= 2 && tag[0] == TAG_NAME && tag[1].isNotEmpty() + fun isTagged(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() - @JvmStatic fun isSameAddress( tag1: Array, tag2: Array, - ) = tag1.match(tag2.name(), tag2.value(), TAG_SIZE) + ): Boolean { + ensure(tag1.has(1)) { return false } + ensure(tag2.has(1)) { return false } + ensure(tag1[0] == tag2[0]) { return false } + ensure(tag1[1] == tag2[1]) { return false } + return true + } @JvmStatic fun isTagged( tag: Array, addressId: String, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] == addressId + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == addressId @JvmStatic fun isTagged( tag: Array, address: ATag, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] == address.toTag() + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == address.toTag() @JvmStatic fun isIn( tag: Array, addressIds: Set, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] in addressIds + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in addressIds @JvmStatic fun isTaggedWithKind( tag: Array, kind: String, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && Address.isOfKind(tag[1], kind) + ) = tag.has(1) && tag[0] == TAG_NAME && Address.isOfKind(tag[1], kind) @JvmStatic fun parseIfOfKind( diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt index 0f59c7897..de7942709 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/events/ETag.kt @@ -22,10 +22,12 @@ package com.vitorpamplona.quartz.nip01Core.tags.events import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes @Immutable @@ -56,32 +58,38 @@ data class ETag( companion object { const val TAG_NAME = "e" - const val TAG_SIZE = 2 @JvmStatic - fun isTagged(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1].length == 64 + fun isTagged(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].length == 64 @JvmStatic fun isTagged( tag: Array, eventId: HexKey, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] == eventId + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == eventId @JvmStatic fun parse(tag: Array): ETag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ETag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @JvmStatic fun parseId(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } @JvmStatic fun parseAsHint(tag: Array): EventIdHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return EventIdHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt index 773b14db2..ac11b4d46 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/hashtags/HashtagTag.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip01Core.tags.hashtags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class HashtagTag { companion object { const val TAG_NAME = "t" - const val TAG_SIZE = 2 @JvmStatic - fun isTagged(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1].isNotEmpty() + fun isTagged(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt index 051199464..c076c4dee 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/kinds/KindTag.kt @@ -20,26 +20,30 @@ */ package com.vitorpamplona.quartz.nip01Core.tags.kinds +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class KindTag { companion object { const val TAG_NAME = "k" - const val TAG_SIZE = 2 - fun match(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun match(tag: Array) = tag.has(1) && tag[0] == TAG_NAME fun isTagged( tag: Array, kind: String, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] == kind + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == kind fun isIn( tag: Array, kinds: Set, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] in kinds + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in kinds @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toInt() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt index 55a2270ac..53e941df9 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/people/PTag.kt @@ -24,12 +24,14 @@ import android.util.Log import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile import com.vitorpamplona.quartz.nip19Bech32.toNpub import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes @Immutable @@ -50,24 +52,25 @@ data class PTag( companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 fun isTagged( tag: Array, key: HexKey, - ): Boolean = tag.size >= 2 && tag[0] == TAG_NAME && tag[1] == key + ): Boolean = tag.has(1) && tag[0] == TAG_NAME && tag[1] == key @JvmStatic fun parse(tag: Tag): PTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return PTag(tag[1], tag.getOrNull(2)) } @JvmStatic fun parseKey(tag: Array): HexKey? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { Log.w("PTag", "Invalid `$TAG_NAME` value ${tag.joinToString(", ")}") return null } @@ -76,7 +79,10 @@ data class PTag( @JvmStatic fun parseAsHint(tag: Array): PubKeyHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return PubKeyHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt index 8c07af9ff..1ad8b8f29 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/tags/references/ReferenceTag.kt @@ -20,34 +20,38 @@ */ package com.vitorpamplona.quartz.nip01Core.tags.references +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip96FileStorage.HttpUrlFormatter +import com.vitorpamplona.quartz.utils.ensure class ReferenceTag { companion object { const val TAG_NAME = "r" - const val TAG_SIZE = 2 @JvmStatic fun isTagged( tag: Array, reference: String, - ): Boolean = tag.size >= 2 && tag[0] == TAG_NAME && tag[1] == reference + ): Boolean = tag.has(1) && tag[0] == TAG_NAME && tag[1] == reference @JvmStatic fun isIn( tag: Array, references: Set, - ): Boolean = tag.size >= 2 && tag[0] == TAG_NAME && tag[1] in references + ): Boolean = tag.has(1) && tag[0] == TAG_NAME && tag[1] in references @JvmStatic fun hasReference(tag: Array): Boolean { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return false + ensure(tag.has(1)) { return false } + ensure(tag[0] == TAG_NAME) { return false } return tag[1].isNotEmpty() } @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt index eab66cef3..d40a858c7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip02FollowList/tags/ContactTag.kt @@ -23,11 +23,13 @@ package com.vitorpamplona.quartz.nip02FollowList.tags import android.util.Log import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip19Bech32.decodePublicKey import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes @Immutable @@ -56,20 +58,23 @@ data class ContactTag( companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 @JvmStatic - fun isTagged(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1].isNotEmpty() + fun isTagged(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): ContactTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ContactTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @JvmStatic fun parseValid(tag: Array): ContactTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return try { ContactTag(decodePublicKey(tag[1]).toHexKey(), tag.getOrNull(2), tag.getOrNull(3)) } catch (e: Exception) { @@ -80,13 +85,17 @@ data class ContactTag( @JvmStatic fun parseKey(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } @JvmStatic fun parseValidKey(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return try { decodePublicKey(tag[1]).toHexKey() } catch (e: Exception) { @@ -97,7 +106,10 @@ data class ContactTag( @JvmStatic fun parseAsHint(tag: Array): PubKeyHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return PubKeyHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt index dc150479c..15ecd3494 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/MarkedETag.kt @@ -22,11 +22,13 @@ package com.vitorpamplona.quartz.nip10Notes.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint import com.vitorpamplona.quartz.nip01Core.tags.events.GenericETag import com.vitorpamplona.quartz.nip19Bech32.entities.NEvent import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes @Immutable @@ -71,7 +73,7 @@ data class MarkedETag( companion object { const val TAG_NAME = "e" - const val TAG_SIZE = 4 + private const val TAG_SIZE = 4 const val ORDER_NAME = 0 const val ORDER_EVT_ID = 1 @@ -183,7 +185,10 @@ data class MarkedETag( @JvmStatic fun parseAsHint(tag: Array): EventIdHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return EventIdHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt index 7b0947b38..d21e0d341 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip10Notes/tags/Positional.kt @@ -48,9 +48,9 @@ fun List.positionalMarkedTags( } }.map { when (it) { - root -> arrayOf(tagName, it, "", "root") - replyingTo -> arrayOf(tagName, it, "", "reply") - forkedFrom -> arrayOf(tagName, it, "", "fork") + root -> arrayOf(tagName, it, "", MarkedETag.MARKER.ROOT) + replyingTo -> arrayOf(tagName, it, "", MarkedETag.MARKER.REPLY) + forkedFrom -> arrayOf(tagName, it, "", MarkedETag.MARKER.FORK) else -> arrayOf(tagName, it) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt index 8c2fd5510..8b2674324 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip13Pow/tags/PoWTag.kt @@ -20,8 +20,10 @@ */ package com.vitorpamplona.quartz.nip13Pow.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes class PoWTag( @@ -34,20 +36,23 @@ class PoWTag( companion object { const val TAG_NAME = "nonce" - const val TAG_SIZE = 2 @JvmStatic - fun hasTagWithContent(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1].isNotEmpty() + fun hasTagWithContent(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): PoWTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return PoWTag(tag[1], tag.getOrNull(2)?.toIntOrNull()) } @JvmStatic fun parseCommitment(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag.getOrNull(2)?.toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt index 8489b1669..4d8becbb8 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip14Subject/SubjectTag.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip14Subject +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class SubjectTag { companion object { const val TAG_NAME = "subject" - const val TAG_SIZE = 2 @JvmStatic - fun hasTagWithContent(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1].isNotEmpty() + fun hasTagWithContent(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt index a44727038..8fe35ea2d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionAlgo.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip17Dm.files.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class EncryptionAlgo { companion object { const val TAG_NAME = "encryption-algorithm" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(1) && tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt index d3ed47c41..6dbfdf91b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionKey.kt @@ -20,20 +20,23 @@ */ package com.vitorpamplona.quartz.nip17Dm.files.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.utils.ensure class EncryptionKey { companion object { const val TAG_NAME = "decryption-key" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(0) && tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): ByteArray? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return runCatching { tag[1].hexToByteArray() }.getOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt index b34eb627e..1a792a3df 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/EncryptionNonce.kt @@ -20,20 +20,23 @@ */ package com.vitorpamplona.quartz.nip17Dm.files.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.core.hexToByteArray import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.utils.ensure class EncryptionNonce { companion object { const val TAG_NAME = "decryption-nonce" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(0) && tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): ByteArray? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return runCatching { tag[1].hexToByteArray() }.getOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt index 38620fd2d..3cae4c9d3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip17Dm/files/tags/FileTypeTag.kt @@ -20,19 +20,23 @@ */ package com.vitorpamplona.quartz.nip17Dm.files.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class FileTypeTag { companion object { const val TAG_NAME = "file-type" - const val TAG_SIZE = 2 fun isIn( tag: Array, mimeTypes: Set, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] in mimeTypes + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in mimeTypes @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt index a0e4ac3a8..cc78b6f5d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QAddressableTag.kt @@ -59,13 +59,13 @@ data class QAddressableTag( override fun toTagArray() = assemble(address, relay) companion object { - const val TAG_SIZE = 2 + const val TAG_NAME = "q" @JvmStatic fun parse(tag: Array): QAddressableTag? { ensure(tag.has(1)) { return null } - ensure(tag[0] == QTag.TAG_NAME) { return null } - ensure(tag[1].isNotEmpty()) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length != 64) { return null } val address = Address.parse(tag[1]) ?: return null return QAddressableTag(address, tag.getOrNull(2)) } @@ -76,12 +76,12 @@ data class QAddressableTag( pubKeyHex: HexKey, dTag: String, relay: String?, - ) = arrayOfNotNull(QTag.TAG_NAME, Address.assemble(kind, pubKeyHex, dTag), relay) + ) = arrayOfNotNull(TAG_NAME, Address.assemble(kind, pubKeyHex, dTag), relay) @JvmStatic fun assemble( address: Address, relay: String?, - ) = arrayOfNotNull(QTag.TAG_NAME, address.toValue(), relay) + ) = arrayOfNotNull(TAG_NAME, address.toValue(), relay) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt index 511bb12d0..995890fd0 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QEventTag.kt @@ -22,8 +22,10 @@ package com.vitorpamplona.quartz.nip18Reposts.quotes import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes @Immutable @@ -47,11 +49,13 @@ data class QEventTag( override fun toTagArray() = assemble(eventId, relay, author) companion object { - const val TAG_SIZE = 2 + const val TAG_NAME = "q" @JvmStatic fun parse(tag: Array): QEventTag? { - if (tag.size < TAG_SIZE || tag[0] != QTag.TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return QEventTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @@ -60,6 +64,6 @@ data class QEventTag( eventId: HexKey, relay: String?, author: HexKey?, - ) = arrayOfNotNull(QTag.TAG_NAME, eventId, relay, author) + ) = arrayOfNotNull(TAG_NAME, eventId, relay, author) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt index 52e6d1490..5feeab571 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip18Reposts/quotes/QTag.kt @@ -20,35 +20,46 @@ */ package com.vitorpamplona.quartz.nip18Reposts.quotes +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint +import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address +import com.vitorpamplona.quartz.utils.ensure interface QTag { fun toTagArray(): Array companion object { const val TAG_NAME = "q" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): QTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } return if (tag[1].length == 64) { - QEventTag.parse(tag) + QEventTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } else { - QAddressableTag.parse(tag) + val address = Address.parse(tag[1]) ?: return null + QAddressableTag(address, tag.getOrNull(2)) } } @JvmStatic fun parseEventAsHint(tag: Array): EventIdHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return EventIdHint(tag[1], tag[2]) } @JvmStatic fun parseAddressAsHint(tag: Array): AddressHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length == 64 || !tag[1].contains(':') || tag[2].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length != 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } + ensure(!tag[1].contains(':')) { return null } return AddressHint(tag[1], tag[2]) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt index 83e94ac49..14410a207 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/CommentEvent.kt @@ -107,8 +107,8 @@ class CommentEvent( ?: tags.lastNotNullOfOrNull(RootEventTag::parseKey) fun replyingToAddressId(): String? = - tags.lastNotNullOfOrNull(RootAddressTag::parseAddress) - ?: tags.lastNotNullOfOrNull(ReplyAddressTag::parseAddress) + tags.lastNotNullOfOrNull(RootAddressTag::parseAddressId) + ?: tags.lastNotNullOfOrNull(ReplyAddressTag::parseAddressId) override fun replyingToAddressOrEvent(): HexKey? = replyingToAddressId() ?: replyingTo() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt index 9e930bbf3..43933ee44 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAddressTag.kt @@ -23,11 +23,11 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class ReplyAddressTag( @@ -38,23 +38,32 @@ class ReplyAddressTag( companion object { const val TAG_NAME = "a" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): ReplyAddressTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ReplyAddressTag(tag[1], tag.getOrNull(2)) } @JvmStatic - fun parseAddress(tag: Array) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parseAddressId(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun parseAsHint(tag: Array): AddressHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length == 64 || !tag[1].contains(':') || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return AddressHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt index 1f647c2d5..c6e8598d7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyAuthorTag.kt @@ -23,10 +23,11 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable data class ReplyAuthorTag( @@ -37,28 +38,32 @@ data class ReplyAuthorTag( companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Tag): ReplyAuthorTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ReplyAuthorTag(tag[1], tag.getOrNull(2)) } @JvmStatic fun parseKey(tag: Tag): HexKey? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } @JvmStatic fun parseAsHint(tag: Array): PubKeyHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return PubKeyHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt index 77f68fbc4..337e6f35b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyEventTag.kt @@ -23,11 +23,12 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference +import com.vitorpamplona.quartz.utils.Hex import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class ReplyEventTag( @@ -39,42 +40,53 @@ class ReplyEventTag( companion object { const val TAG_NAME = "e" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun isTagged( tag: Array, eventId: String, - ) = tag.match(TAG_NAME, eventId, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == eventId @JvmStatic fun isIn( tag: Array, eventIds: Set, - ) = tag.match(TAG_NAME, eventIds, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in eventIds @JvmStatic fun parse(tag: Array): ReplyEventTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ReplyEventTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @JvmStatic - fun parseKey(tag: Array) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parseKey(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + return tag[1] + } @JvmStatic fun parseValidKey(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(Hex.isHex(tag[1])) { return null } return tag[1] } @JvmStatic fun parseAsHint(tag: Array): EventIdHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return EventIdHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt index 9926fa8ff..f0e2299e8 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyIdentifierTag.kt @@ -22,24 +22,28 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeoHash import com.vitorpamplona.quartz.nip73ExternalIds.ExternalId import com.vitorpamplona.quartz.nip73ExternalIds.GeohashId import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class ReplyIdentifierTag { companion object { const val TAG_NAME = "i" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic - fun parse(tag: Tag) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parse(tag: Tag): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun assemble( diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt index f3a0028ed..43647bcb2 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/ReplyKindTag.kt @@ -21,36 +21,36 @@ package com.vitorpamplona.quartz.nip22Comments.tags import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.matchAndHasValue -import com.vitorpamplona.quartz.nip01Core.core.valueToIntIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip73ExternalIds.ExternalId +import com.vitorpamplona.quartz.utils.ensure class ReplyKindTag { companion object { const val TAG_NAME = "k" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) - - @JvmStatic - fun isTagged(tag: Tag) = tag.matchAndHasValue(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun isTagged( tag: Tag, kind: String, - ) = tag.match(TAG_NAME, kind, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == kind @JvmStatic fun isIn( tag: Tag, kinds: Set, - ) = tag.match(TAG_NAME, kinds, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in kinds @JvmStatic - fun parse(tag: Tag) = tag.valueToIntIfMatches(TAG_NAME, TAG_SIZE) + fun parse(tag: Tag): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun assemble(kind: String) = arrayOf(TAG_NAME, kind) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt index 3241fbfc6..46263abe2 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAddressTag.kt @@ -24,8 +24,6 @@ import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag import com.vitorpamplona.quartz.nip01Core.core.has -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.utils.arrayOfNotNull @@ -40,26 +38,27 @@ class RootAddressTag( companion object { const val TAG_NAME = "A" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun isTagged( tag: Array, addressId: String, - ) = tag.match(TAG_NAME, addressId, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == addressId @JvmStatic fun isIn( tag: Array, addressIds: Set, - ) = tag.match(TAG_NAME, addressIds, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in addressIds @JvmStatic fun parse(tag: Array): RootAddressTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return RootAddressTag(tag[1], tag.getOrNull(2)) } @@ -72,11 +71,19 @@ class RootAddressTag( } @JvmStatic - fun parseAddress(tag: Array) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parseAddressId(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun parseAsHint(tag: Array): AddressHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length == 64 || !tag[1].contains(':') || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return AddressHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt index dcae0d9f9..e548f60bc 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootAuthorTag.kt @@ -24,11 +24,11 @@ import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.PUBKEY_LENGTH import com.vitorpamplona.quartz.nip01Core.core.Tag +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.PubKeyHint import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag import com.vitorpamplona.quartz.utils.arrayOfNotNull -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract +import com.vitorpamplona.quartz.utils.ensure @Immutable data class RootAuthorTag( @@ -41,7 +41,7 @@ data class RootAuthorTag( const val TAG_NAME = "P" @JvmStatic - fun match(tag: Tag) = tag.size > 1 && tag[0] == TAG_NAME + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Tag): ReplyAuthorTag? { @@ -65,19 +65,13 @@ data class RootAuthorTag( @JvmStatic fun parseAsHint(tag: Array): PubKeyHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != PUBKEY_LENGTH || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return PubKeyHint(tag[1], tag[2]) } - @OptIn(ExperimentalContracts::class) - inline fun ensure( - condition: Boolean, - exit: () -> Nothing, - ) { - contract { returns() implies condition } - if (!condition) exit() - } - @JvmStatic fun assemble( pubkey: HexKey, diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt index c0d546f92..9796e5ec6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootEventTag.kt @@ -23,11 +23,12 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint import com.vitorpamplona.quartz.nip01Core.tags.events.EventReference +import com.vitorpamplona.quartz.utils.Hex import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class RootEventTag( @@ -39,42 +40,53 @@ class RootEventTag( companion object { const val TAG_NAME = "E" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun isTagged( tag: Array, eventId: String, - ) = tag.match(TAG_NAME, eventId, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == eventId @JvmStatic fun isIn( tag: Array, eventIds: Set, - ) = tag.match(TAG_NAME, eventIds, TAG_SIZE) + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in eventIds @JvmStatic fun parse(tag: Array): RootEventTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return RootEventTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @JvmStatic - fun parseKey(tag: Array) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parseKey(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + return tag[1] + } @JvmStatic fun parseValidKey(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(Hex.isHex(tag[1])) { return null } return tag[1] } @JvmStatic fun parseAsHint(tag: Array): EventIdHint? { - if (tag.size < 3 || tag[0] != TAG_NAME || tag[1].length != 64 || tag[2].isEmpty()) return null + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[2].isNotEmpty()) { return null } return EventIdHint(tag[1], tag[2]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt index 34aa37a9d..d896b3e66 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootIdentifierTag.kt @@ -22,24 +22,28 @@ package com.vitorpamplona.quartz.nip22Comments.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.tags.geohash.GeoHash import com.vitorpamplona.quartz.nip73ExternalIds.ExternalId import com.vitorpamplona.quartz.nip73ExternalIds.GeohashId import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class RootIdentifierTag { companion object { const val TAG_NAME = "I" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic - fun parse(tag: Tag) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parse(tag: Tag): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun assemble( diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt index bbbe5861d..7a1a31767 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip22Comments/tags/RootKindTag.kt @@ -21,20 +21,24 @@ package com.vitorpamplona.quartz.nip22Comments.tags import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip73ExternalIds.ExternalId +import com.vitorpamplona.quartz.utils.ensure class RootKindTag { companion object { const val TAG_NAME = "K" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic - fun parse(tag: Tag) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parse(tag: Tag): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun assemble(kind: String): Tag = arrayOf(TAG_NAME, kind) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt index d7e74286e..0ab6c6714 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/ImageTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip23LongContent.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ImageTag { companion object { const val TAG_NAME = "image" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt index 671348f27..21f33adb4 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/PublishedAtTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip23LongContent.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class PublishedAtTag { companion object { const val TAG_NAME = "published_at" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt index 1e04d3b56..6acbac79d 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/SummaryTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip23LongContent.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class SummaryTag { companion object { const val TAG_NAME = "summary" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt index 409c4eb1d..77b6ab6d6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip23LongContent/tags/TitleTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip23LongContent.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class TitleTag { companion object { const val TAG_NAME = "title" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt index b28d37465..8a7df1c4a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip31Alts/AltTag.kt @@ -20,18 +20,22 @@ */ package com.vitorpamplona.quartz.nip31Alts +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class AltTag { companion object { const val TAG_NAME = "alt" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } @JvmStatic - fun assemble(altDescriptor: String = "") = arrayOf(TAG_NAME, altDescriptor) + fun assemble(altDescriptor: String) = arrayOf(TAG_NAME, altDescriptor) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt index 47b1e1f18..b4a95634e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/CloneTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip34Git.repository.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class CloneTag { companion object { const val TAG_NAME = "clone" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt index 4256d7efe..faea7e0d8 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/DescriptionTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip34Git.repository.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class DescriptionTag { companion object { const val TAG_NAME = "description" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt index 8fc6aff04..147b52d35 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/NameTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip34Git.repository.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class NameTag { companion object { const val TAG_NAME = "name" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt index 5c5445856..3dae53fa3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip34Git/repository/tags/WebTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip34Git.repository.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class WebTag { companion object { const val TAG_NAME = "web" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt index 85697ae11..47feee58c 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/BtihTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip35Torrents.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class BtihTag { companion object { const val TAG_NAME = "btih" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt index 895eb423c..0639907fe 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/FileTag.kt @@ -21,7 +21,9 @@ package com.vitorpamplona.quartz.nip35Torrents.tags import androidx.compose.runtime.Immutable +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip46RemoteSigner.getOrNull +import com.vitorpamplona.quartz.utils.ensure @Immutable class FileTag( @@ -32,18 +34,21 @@ class FileTag( companion object { const val TAG_NAME = "file" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): FileTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return FileTag(tag[1], tag.getOrNull(2)?.toLongOrNull()) } @JvmStatic fun parseBytes(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - return tag.getOrNull(2)?.toLongOrNull() + ensure(tag.has(2)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[2].isNotEmpty()) { return null } + return tag[2].toLongOrNull() } @JvmStatic diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt index 744aad94d..1e0786ebf 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/InfoHashTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip35Torrents.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class InfoHashTag { companion object { const val TAG_NAME = "x" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt index 8282c3670..4e154418e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip35Torrents/tags/TrackerTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip35Torrents.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class TrackerTag { companion object { const val TAG_NAME = "tracker" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt index 934a4637b..fb1b44148 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/CurrentParticipantsTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class CurrentParticipantsTag { companion object { const val TAG_NAME = "current_participants" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt index 0597b1d54..26d212547 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/EndsTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class EndsTag { companion object { const val TAG_NAME = "ends" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt index a77348d0d..c48c004c3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/ParticipantTag.kt @@ -23,9 +23,10 @@ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.isNotName +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure enum class ROLE( val code: String, @@ -43,40 +44,43 @@ data class ParticipantTag( ) : PubKeyReferenceTag { companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 fun isIn( tag: Array, keys: Set, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] in keys + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in keys @JvmStatic fun isHost(tag: Tag): Boolean { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return false - if (tag[1].length != 64) return false - if (tag.getOrNull(3).equals(ROLE.HOST.code)) return true - return false + ensure(tag.has(3)) { return false } + ensure(tag[0] == TAG_NAME) { return false } + ensure(tag[1].length == 64) { return false } + ensure(tag[3] == ROLE.HOST.code) { return false } + return true } @JvmStatic fun parse(tag: Tag): ParticipantTag? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ParticipantTag(tag[1], tag.getOrNull(2), tag.getOrNull(3), tag.getOrNull(4)) } @JvmStatic fun parseHost(tag: Tag): ParticipantTag? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null - if (!tag.getOrNull(3).equals(ROLE.HOST.code)) return null - return ParticipantTag(tag[1], tag.getOrNull(2), tag.getOrNull(3), tag.getOrNull(4)) + ensure(tag.has(3)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } + ensure(tag[3] == ROLE.HOST.code) { return null } + return ParticipantTag(tag[1], tag[2], tag[3], tag.getOrNull(4)) } @JvmStatic fun parseKey(tag: Tag): String? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt index fda64e467..70627f607 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/RelayListTag.kt @@ -20,16 +20,20 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class RelayListTag( val relayUrls: List, ) { companion object { const val TAG_NAME = "relays" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): RelayListTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } val relays = tag.mapIndexedNotNull { index, s -> if (index == 0) null else s diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt index 8c6cb4488..7a094d643 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StartsTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class StartsTag { companion object { const val TAG_NAME = "starts" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt index d6e651b9e..f41dcfc05 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StatusTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class StatusTag { enum class STATUS( val code: String, @@ -34,11 +37,12 @@ class StatusTag { companion object { const val TAG_NAME = "status" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt index 7303e1a44..667cf742e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/StreamingTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class StreamingTag { companion object { const val TAG_NAME = "streaming" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt index 52bbeac76..ac34c4bf6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip53LiveActivities/streaming/tags/TotalParticipantsTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class TotalParticipantsTag { companion object { const val TAG_NAME = "total_participants" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt index 192ade51d..66feb1396 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip57Zaps/zapraiser/ZapRaiserTag.kt @@ -31,7 +31,7 @@ class ZapRaiserTag( fun toTagArray() = assemble(amountInSats) companion object { - val TAG_NAME = "zapraiser" + const val TAG_NAME = "zapraiser" @JvmStatic fun parse(tags: Array): ZapRaiserTag? { diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt index 4e4fed010..fc378cc8a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/DurationTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip71Video.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class DurationTag { companion object { const val TAG_NAME = "duration" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt index 6feb0fea0..2d4a09bd4 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/SegmentTag.kt @@ -20,7 +20,9 @@ */ package com.vitorpamplona.quartz.nip71Video.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure class SegmentTag( val start: String, // HH:MM:SS.sss @@ -32,11 +34,14 @@ class SegmentTag( companion object { const val TAG_NAME = "segment" - const val TAG_SIZE = 4 @JvmStatic fun parse(tag: Array): SegmentTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(3)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + ensure(tag[2].isNotEmpty()) { return null } + ensure(tag[3].isNotEmpty()) { return null } return SegmentTag(tag[1], tag[2], tag[3], tag.getOrNull(4)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt index 1f0680f46..a624e0c09 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip71Video/tags/TextTrackTag.kt @@ -21,8 +21,10 @@ package com.vitorpamplona.quartz.nip71Video.tags import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.bytesUsedInMemory +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.pointerSizeInBytes data class TextTrackTag( @@ -38,11 +40,12 @@ data class TextTrackTag( companion object { const val TAG_NAME = "text-track" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): TextTrackTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return TextTrackTag(tag[1], tag.getOrNull(2)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt index 84a2edb9d..5e76b7ed9 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/DescriptionTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class DescriptionTag { companion object { const val TAG_NAME = "description" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt index 9bae1d46a..2f3a7dbe3 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ImageTag.kt @@ -20,8 +20,10 @@ */ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure class ImageTag( val imageUrl: String, @@ -29,12 +31,12 @@ class ImageTag( ) { companion object { const val TAG_NAME = "image" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): ImageTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null - if (tag[1].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } val dims = tag.getOrNull(2)?.let { DimensionTag.parse(it) } return ImageTag(tag[1], dims) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt index 08d901cc2..ddd2b46a2 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/ModeratorTag.kt @@ -23,9 +23,10 @@ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Tag -import com.vitorpamplona.quartz.nip01Core.core.isNotName +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure @Immutable data class ModeratorTag( @@ -37,19 +38,20 @@ data class ModeratorTag( companion object { const val TAG_NAME = "p" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Tag): ModeratorTag? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return ModeratorTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } @JvmStatic fun parseKey(tag: Tag): String? { - if (tag.isNotName(TAG_NAME, TAG_SIZE)) return null - if (tag[1].length != 64) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].length == 64) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt index 0c66da66d..5f23b0f82 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/NameTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class NameTag { companion object { const val TAG_NAME = "name" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt index a70f2f7d9..6e5c4dd14 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RelayTag.kt @@ -20,7 +20,9 @@ */ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure class RelayTag( val url: String, @@ -30,11 +32,12 @@ class RelayTag( companion object { const val TAG_NAME = "relay" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): RelayTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return RelayTag(tag[1], tag.getOrNull(2)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt index 467216f8f..3908eca08 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip72ModCommunities/definition/tags/RulesTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip72ModCommunities.definition.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class RulesTag { companion object { const val TAG_NAME = "rules" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt index e5c24cae3..177c985ab 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/AmountTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip75ZapGoals.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class AmountTag { companion object { const val TAG_NAME = "amount" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt index 2fbd2a885..2af7ec8d6 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/ClosedAtTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip75ZapGoals.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ClosedAtTag { companion object { const val TAG_NAME = "closed_at" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Long? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toLongOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt index bb5c0811a..9f49ce761 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip75ZapGoals/tags/RelayListTag.kt @@ -20,16 +20,20 @@ */ package com.vitorpamplona.quartz.nip75ZapGoals.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class RelayListTag( val relayUrls: List, ) { companion object { const val TAG_NAME = "relays" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): RelayListTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } val relays = tag.mapIndexedNotNull { index, s -> if (index == 0) null else s diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt index 6e46a32e7..80daa368f 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip84Highlights/tags/ContextTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip84Highlights.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ContextTag { companion object { const val TAG_NAME = "context" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt index 94f5f798d..8c18bf480 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/definition/tags/PlatformLinkTag.kt @@ -21,6 +21,7 @@ package com.vitorpamplona.quartz.nip89AppHandlers.definition.tags import com.vitorpamplona.quartz.nip01Core.core.Tag +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip89AppHandlers.PlatformType import com.vitorpamplona.quartz.utils.arrayOfNotNull @@ -32,14 +33,10 @@ class PlatformLinkTag( fun toTagArray() = assemble(platform, uri, entityType) companion object { - const val TAG_SIZE = 3 - @JvmStatic fun match(tag: Tag): Boolean = - if (tag.size >= TAG_SIZE) { - tag[0] == PlatformType.IOS.code || - tag[0] == PlatformType.WEB.code || - tag[0] == PlatformType.ANDROID.code + if (tag.has(2)) { + tag[0] == PlatformType.IOS.code || tag[0] == PlatformType.WEB.code || tag[0] == PlatformType.ANDROID.code } else { false } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt index 0b3db29b5..4b98181e7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/AppRecommendationEvent.kt @@ -43,7 +43,7 @@ class AppRecommendationEvent( ) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) { fun recommendations() = tags.mapNotNull(RecommendationTag::parse) - fun recommendationAddresses() = tags.mapNotNull(RecommendationTag::parseAddress) + fun recommendationAddresses() = tags.mapNotNull(RecommendationTag::parseAddressId) companion object { const val KIND = 31989 diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt index 045510e69..22c8fea76 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip89AppHandlers/recommendation/tags/RecommendationTag.kt @@ -23,8 +23,6 @@ package com.vitorpamplona.quartz.nip89AppHandlers.recommendation.tags import androidx.compose.runtime.Immutable import com.vitorpamplona.quartz.nip01Core.core.Tag import com.vitorpamplona.quartz.nip01Core.core.has -import com.vitorpamplona.quartz.nip01Core.core.match -import com.vitorpamplona.quartz.nip01Core.core.valueIfMatches import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import com.vitorpamplona.quartz.utils.arrayOfNotNull import com.vitorpamplona.quartz.utils.ensure @@ -39,10 +37,9 @@ class RecommendationTag( companion object { const val TAG_NAME = "a" - const val TAG_SIZE = 2 @JvmStatic - fun match(tag: Tag) = tag.match(TAG_NAME, TAG_SIZE) + fun match(tag: Tag) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): RecommendationTag? { @@ -54,7 +51,12 @@ class RecommendationTag( } @JvmStatic - fun parseAddress(tag: Array) = tag.valueIfMatches(TAG_NAME, TAG_SIZE) + fun parseAddressId(tag: Array): String? { + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } + return tag[1] + } @JvmStatic fun assemble( diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt index 7f8c1c8d1..1c7d89153 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip92IMeta/IMetaTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip92IMeta +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class IMetaTag( val url: String, val properties: Map>, @@ -38,10 +41,11 @@ class IMetaTag( companion object { const val TAG_NAME = "imeta" const val ANCHOR_PROPERTY = "url" - const val TAG_SIZE = 2 fun parse(tag: Array): IMetaTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } val allTags = parseIMeta(tag) val url = allTags.get(ANCHOR_PROPERTY)?.firstOrNull() diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt index 329314d84..57c646976 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/BlurhashTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class BlurhashTag { companion object { const val TAG_NAME = "blurhash" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt index dcfd011ca..515b7c916 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/DimensionTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class DimensionTag( val width: Int, val height: Int, @@ -34,11 +37,12 @@ class DimensionTag( companion object { const val TAG_NAME = "dim" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): DimensionTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return parse(tag[1]) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt index 4eca6fd06..b00bfc43c 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/FallbackTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class FallbackTag { companion object { const val TAG_NAME = "fallback" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt index 9880e9162..adf394c3a 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/HashSha256Tag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class HashSha256Tag { companion object { const val TAG_NAME = "x" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME || tag[1].isEmpty()) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt index 7aa7274a2..f8423bd3e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ImageTag.kt @@ -21,7 +21,9 @@ package com.vitorpamplona.quartz.nip94FileMetadata.tags import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure class ImageTag( val imageUrl: String, @@ -29,11 +31,12 @@ class ImageTag( ) { companion object { const val TAG_NAME = "image" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): ImageTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return ImageTag(tag[1], tag.getOrNull(2)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt index 9bd916cd7..d608a6f64 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MagnetTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MagnetTag { companion object { const val TAG_NAME = "magnet" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt index 416b3f0a1..c0555f089 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/MimeTypeTag.kt @@ -20,19 +20,23 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MimeTypeTag { companion object { const val TAG_NAME = "m" - const val TAG_SIZE = 2 fun isIn( tag: Array, mimeTypes: Set, - ) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME && tag[1] in mimeTypes + ) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in mimeTypes @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt index 6cc31f954..f17d01e75 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/OriginalHashTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class OriginalHashTag { companion object { const val TAG_NAME = "ox" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt index ca4703c05..18c6a9315 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ServiceTag.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ServiceTag { companion object { const val TAG_NAME = "service" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(0) && tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt index 4548ea5f5..645a77d1f 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SizeTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class SizeTag { companion object { const val TAG_NAME = "size" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): Int? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1].toIntOrNull() } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt index b854ab7a6..b0a405fca 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/SummaryTag.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class SummaryTag { companion object { const val TAG_NAME = "summary" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(1) && tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt index e11faa1be..52e53e202 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/ThumbTag.kt @@ -21,7 +21,9 @@ package com.vitorpamplona.quartz.nip94FileMetadata.tags import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure class ThumbTag( val imageUrl: String, @@ -29,11 +31,12 @@ class ThumbTag( ) { companion object { const val TAG_NAME = "thumb" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): ThumbTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return ThumbTag(tag[1], tag.getOrNull(2)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt index 93b87b03e..4ea1a7d4b 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/TorrentInfoHash.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class TorrentInfoHash { companion object { const val TAG_NAME = "i" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt index 4be128be8..05bcd0a91 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip94FileMetadata/tags/UrlTag.kt @@ -20,17 +20,21 @@ */ package com.vitorpamplona.quartz.nip94FileMetadata.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class UrlTag { companion object { const val TAG_NAME = "url" - const val TAG_SIZE = 2 @JvmStatic - fun isTag(tag: Array) = tag.size >= TAG_SIZE && tag[0] == TAG_NAME + fun isTag(tag: Array) = tag.has(1) && tag[0] == TAG_NAME && tag[1].isNotEmpty() @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt index 4e326bb9d..2b926fb6e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip96FileStorage/config/tags/ServerTag.kt @@ -20,16 +20,20 @@ */ package com.vitorpamplona.quartz.nip96FileStorage.config.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ServerTag { companion object { const val TAG_NAME = "server" - const val TAG_SIZE = 2 fun isTag(tag: Array) = tag[0] == TAG_NAME @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt index 5459cfdf5..bd127fd4f 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/MethodTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip98HttpAuth.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class MethodTag { companion object { const val TAG_NAME = "method" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt index f8ae6d583..1c342f818 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/PayloadHashTag.kt @@ -21,17 +21,20 @@ package com.vitorpamplona.quartz.nip98HttpAuth.tags import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.utils.ensure import com.vitorpamplona.quartz.utils.sha256.sha256 class PayloadHashTag { companion object { const val TAG_NAME = "payload" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): HexKey? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt index a8f1afd40..1895606d7 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip98HttpAuth/tags/UrlTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip98HttpAuth.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class UrlTag { companion object { const val TAG_NAME = "u" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt index 658a694c6..2071cf817 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/ConditionTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip99Classifieds.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class ConditionTag { enum class CONDITION( val value: String, @@ -35,11 +38,12 @@ class ConditionTag { companion object { const val TAG_NAME = "condition" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt index 1d8966ef1..1a7efcd9e 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/LocationTag.kt @@ -20,14 +20,18 @@ */ package com.vitorpamplona.quartz.nip99Classifieds.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class LocationTag { companion object { const val TAG_NAME = "location" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt index 48c2e4801..e432aef23 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/PriceTag.kt @@ -20,7 +20,9 @@ */ package com.vitorpamplona.quartz.nip99Classifieds.tags +import com.vitorpamplona.quartz.nip01Core.core.has import com.vitorpamplona.quartz.utils.arrayOfNotNull +import com.vitorpamplona.quartz.utils.ensure data class PriceTag( val amount: String, @@ -31,11 +33,12 @@ data class PriceTag( companion object { const val TAG_NAME = "price" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): PriceTag? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return PriceTag(tag[1], tag.getOrNull(2), tag.getOrNull(3)) } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt index d4365b82f..149cc9c74 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip99Classifieds/tags/StatusTag.kt @@ -20,6 +20,9 @@ */ package com.vitorpamplona.quartz.nip99Classifieds.tags +import com.vitorpamplona.quartz.nip01Core.core.has +import com.vitorpamplona.quartz.utils.ensure + class StatusTag { enum class STATUS( val value: String, @@ -33,11 +36,12 @@ class StatusTag { companion object { const val TAG_NAME = "status" - const val TAG_SIZE = 2 @JvmStatic fun parse(tag: Array): String? { - if (tag.size < TAG_SIZE || tag[0] != TAG_NAME) return null + ensure(tag.has(1)) { return null } + ensure(tag[0] == TAG_NAME) { return null } + ensure(tag[1].isNotEmpty()) { return null } return tag[1] }