Changes
56 changed files (+37/-11923)
-
-
@@ -1,20 +1,16 @@TEST := go test TEST_FLAGS ?= -v TEST_TARGET ?= ./... GO111MODULE=on export GOPATH += $$GOPATH:$(shell pwd) test: $(TEST) $(TEST_FLAGS) $(TEST_TARGET) activitypub.coverprofile: TEST_TARGET := activitypub activitypub.coverprofile: TEST_FLAGS += -covermode=count -coverprofile=$(TEST_TARGET).coverprofile activitypub.coverprofile: go get -v -u github.com/buger/jsonparser activitypub.coverprofile: test activitypub.coverprofile: TEST_TARGET := jsonld activitypub.coverprofile: TEST_FLAGS += -covermode=count -coverprofile=$(TEST_TARGET).coverprofile activitypub.coverprofile: test coverprofile: TEST_TARGET := . coverprofile: TEST_FLAGS += -covermode=count -coverprofile=$(TEST_TARGET).coverprofile coverprofile: test clean: $(RM) -v *.coverprofile
-
-
activitystreams/activity.go (deleted)
-
@@ -1,1551 +0,0 @@package activitystreams import ( "time" ) // Activity Types const ( AcceptType ActivityVocabularyType = "Accept" AddType ActivityVocabularyType = "Add" AnnounceType ActivityVocabularyType = "Announce" ArriveType ActivityVocabularyType = "Arrive" BlockType ActivityVocabularyType = "Block" CreateType ActivityVocabularyType = "Create" DeleteType ActivityVocabularyType = "Delete" DislikeType ActivityVocabularyType = "Dislike" FlagType ActivityVocabularyType = "Flag" FollowType ActivityVocabularyType = "Follow" IgnoreType ActivityVocabularyType = "Ignore" InviteType ActivityVocabularyType = "Invite" JoinType ActivityVocabularyType = "Join" LeaveType ActivityVocabularyType = "Leave" LikeType ActivityVocabularyType = "Like" ListenType ActivityVocabularyType = "Listen" MoveType ActivityVocabularyType = "Move" OfferType ActivityVocabularyType = "Offer" QuestionType ActivityVocabularyType = "Question" RejectType ActivityVocabularyType = "Reject" ReadType ActivityVocabularyType = "Read" RemoveType ActivityVocabularyType = "Remove" TentativeRejectType ActivityVocabularyType = "TentativeReject" TentativeAcceptType ActivityVocabularyType = "TentativeAccept" TravelType ActivityVocabularyType = "Travel" UndoType ActivityVocabularyType = "Undo" UpdateType ActivityVocabularyType = "Update" ViewType ActivityVocabularyType = "View" ) var validContentManagementActivityTypes = [...]ActivityVocabularyType{ CreateType, DeleteType, UpdateType, } var validCollectionManagementActivityTypes = [...]ActivityVocabularyType{ AddType, MoveType, RemoveType, } var validReactionsActivityTypes = [...]ActivityVocabularyType{ AcceptType, BlockType, DislikeType, FlagType, IgnoreType, LikeType, RejectType, TentativeAcceptType, TentativeRejectType, } var validEventRSVPActivityTypes = [...]ActivityVocabularyType{ AcceptType, IgnoreType, InviteType, RejectType, TentativeAcceptType, TentativeRejectType, } var validGroupManagementActivityTypes = [...]ActivityVocabularyType{ AddType, JoinType, LeaveType, RemoveType, } var validContentExperienceActivityTypes = [...]ActivityVocabularyType{ ArriveType, LeaveType, TravelType, } var validGeoSocialEventsActivityTypes = [...]ActivityVocabularyType{ ArriveType, LeaveType, TravelType, } var validNotificationActivityTypes = [...]ActivityVocabularyType{ AnnounceType, } var validQuestionActivityTypes = [...]ActivityVocabularyType{ QuestionType, } var validRelationshipManagementActivityTypes = [...]ActivityVocabularyType{ AcceptType, AddType, BlockType, CreateType, DeleteType, FollowType, IgnoreType, InviteType, RejectType, } var validNegatingActivityTypes = [...]ActivityVocabularyType{ UndoType, } var validOffersActivityTypes = [...]ActivityVocabularyType{ OfferType, } var validIntransitiveActivityTypes = [...]ActivityVocabularyType{ ArriveType, TravelType, QuestionType, } var validActivityTypes = [...]ActivityVocabularyType{ AcceptType, AddType, AnnounceType, BlockType, CreateType, DeleteType, DislikeType, FlagType, FollowType, IgnoreType, InviteType, JoinType, LeaveType, LikeType, ListenType, MoveType, OfferType, RejectType, ReadType, RemoveType, TentativeRejectType, TentativeAcceptType, UndoType, UpdateType, ViewType, // Actor Types } // Activity is a subtype of Object that describes some form of action that may happen, // is currently happening, or has already happened. // The Activity type itself serves as an abstract base type for all types of activities. // It is important to note that the Activity type itself does not carry any specific semantics // about the kind of action being taken. type Activity struct { Parent // Actor describes one or more entities that either performed or are expected to perform the activity. // Any single activity can have multiple actors. The actor may be specified using an indirect Link. Actor Item `jsonld:"actor,omitempty"` // Target describes the indirect object, or target, of the activity. // The precise meaning of the target is largely dependent on the type of action being described // but will often be the object of the English preposition "to". // For instance, in the activity "John added a movie to his wishlist", // the target of the activity is John's wishlist. An activity can have more than one target. Target Item `jsonld:"target,omitempty"` // Result describes the result of the activity. For instance, if a particular action results in the creation // of a new resource, the result property can be used to describe that new resource. Result Item `jsonld:"result,omitempty"` // Origin describes an indirect object of the activity from which the activity is directed. // The precise meaning of the origin is the object of the English preposition "from". // For instance, in the activity "John moved an item to List B from List A", the origin of the activity is "List A". Origin Item `jsonld:"origin,omitempty"` // Instrument identifies one or more objects used (or to be used) in the completion of an Activity. Instrument Item `jsonld:"instrument,omitempty"` // Object When used within an Activity, describes the direct object of the activity. // For instance, in the activity "John added a movie to his wishlist", // the object of the activity is the movie added. // When used within a Relationship describes the entity to which the subject is related. Object Item `jsonld:"object,omitempty"` } // IntransitiveActivity Instances of IntransitiveActivity are a subtype of Activity representing intransitive actions. // The object property is therefore inappropriate for these activities. type IntransitiveActivity struct { Parent // Actor describes one or more entities that either performed or are expected to perform the activity. // Any single activity can have multiple actors. The actor may be specified using an indirect Link. Actor Actor `jsonld:"actor,omitempty"` // Target describes the indirect object, or target, of the activity. // The precise meaning of the target is largely dependent on the type of action being described // but will often be the object of the English preposition "to". // For instance, in the activity "John added a movie to his wishlist", // the target of the activity is John's wishlist. An activity can have more than one target. Target Item `jsonld:"target,omitempty"` // Result describes the result of the activity. For instance, if a particular action results in the creation // of a new resource, the result property can be used to describe that new resource. Result Item `jsonld:"result,omitempty"` // Origin describes an indirect object of the activity from which the activity is directed. // The precise meaning of the origin is the object of the English preposition "from". // For instance, in the activity "John moved an item to List B from List A", the origin of the activity is "List A". Origin Item `jsonld:"origin,omitempty"` // Instrument identifies one or more objects used (or to be used) in the completion of an Activity. Instrument Item `jsonld:"instrument,omitempty"` } type ( // Accept indicates that the actor accepts the object. The target property can be used in certain circumstances to indicate // the context into which the object has been accepted. Accept Activity // Add indicates that the actor has added the object to the target. If the target property is not explicitly specified, // the target would need to be determined implicitly by context. // The origin can be used to identify the context from which the object originated. Add Activity // Announce indicates that the actor is calling the target's attention the object. // The origin typically has no defined meaning. Announce Activity // Arrive is an IntransitiveActivity that indicates that the actor has arrived at the location. // The origin can be used to identify the context from which the actor originated. // The target typically has no defined meaning. Arrive IntransitiveActivity // Block indicates that the actor is blocking the object. Blocking is a stronger form of Ignore. // The typical use is to support social systems that allow one user to block activities or content of other users. // The target and origin typically have no defined meaning. Block Ignore // Create indicates that the actor has created the object. Create Activity // Delete indicates that the actor has deleted the object. // If specified, the origin indicates the context from which the object was deleted. Delete Activity // Dislike indicates that the actor dislikes the object. Dislike Activity // Flag indicates that the actor is "flagging" the object. // Flagging is defined in the sense common to many social platforms as reporting content as being // inappropriate for any number of reasons. Flag Activity // Follow indicates that the actor is "following" the object. Following is defined in the sense typically used within // Social systems in which the actor is interested in any activity performed by or on the object. // The target and origin typically have no defined meaning. Follow Activity // Ignore indicates that the actor is ignoring the object. The target and origin typically have no defined meaning. Ignore Activity // Invite is a specialization of Offer in which the actor is extending an invitation for the object to the target. Invite Offer // Join indicates that the actor has joined the object. The target and origin typically have no defined meaning. Join Activity // Leave indicates that the actor has left the object. The target and origin typically have no meaning. Leave Activity // Like indicates that the actor likes, recommends or endorses the object. // The target and origin typically have no defined meaning. Like Activity // Listen inherits all properties from Activity. Listen Activity // Move indicates that the actor has moved object from origin to target. // If the origin or target are not specified, either can be determined by context. Move Activity // Offer indicates that the actor is offering the object. // If specified, the target indicates the entity to which the object is being offered. Offer Activity // Reject indicates that the actor is rejecting the object. The target and origin typically have no defined meaning. Reject Activity // Read indicates that the actor has read the object. Read Activity // Remove indicates that the actor is removing the object. If specified, // the origin indicates the context from which the object is being removed. Remove Activity // TentativeReject is a specialization of Reject in which the rejection is considered tentative. TentativeReject Reject // TentativeAccept is a specialization of Accept indicating that the acceptance is tentative. TentativeAccept Accept // Travel indicates that the actor is traveling to target from origin. // Travel is an IntransitiveObject whose actor specifies the direct object. // If the target or origin are not specified, either can be determined by context. Travel IntransitiveActivity // Undo indicates that the actor is undoing the object. In most cases, the object will be an Activity describing // some previously performed action (for instance, a person may have previously "liked" an article but, // for whatever reason, might choose to undo that like at some later point in time). // The target and origin typically have no defined meaning. Undo Activity // Update indicates that the actor has updated the object. Note, however, that this vocabulary does not define a mechanism // for describing the actual set of modifications made to object. // The target and origin typically have no defined meaning. Update Activity // View indicates that the actor has viewed the object. View Activity ) // Question represents a question being asked. Question objects are an extension of IntransitiveActivity. // That is, the Question object is an Activity, but the direct object is the question // itself and therefore it would not contain an object property. // Either of the anyOf and oneOf properties may be used to express possible answers, // but a Question object must not have both properties. type Question struct { // ID providesthe globally unique identifier for an Activity Pub Object or Link. ID ObjectID `jsonld:"id,omitempty"` // Type identifies the Activity Pub Object or Link type. Multiple values may be specified. Type ActivityVocabularyType `jsonld:"type,omitempty"` // Name a simple, human-readable, plain-text name for the object. // HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged values. Name NaturalLanguageValue `jsonld:"name,omitempty,collapsible"` // Attachment identifies a resource attached or related to an object that potentially requires special handling. // The intent is to provide a model that is at least semantically similar to attachments in email. Attachment Item `jsonld:"attachment,omitempty"` // AttributedTo identifies one or more entities to which this object is attributed. The attributed entities might not be Actors. // For instance, an object might be attributed to the completion of another activity. AttributedTo Item `jsonld:"attributedTo,omitempty"` // Audience identifies one or more entities that represent the total population of entities // for which the object can considered to be relevant. Audience Item `jsonld:"audience,omitempty"` // Content the content or textual representation of the Activity Pub Object encoded as a JSON string. // By default, the value of content is HTML. // The mediaType property can be used in the object to indicate a different content type. // (The content MAY be expressed using multiple language-tagged values.) Content NaturalLanguageValue `jsonld:"content,omitempty,collapsible"` // Context identifies the context within which the object exists or an activity was performed. // The notion of "context" used is intentionally vague. // The intended function is to serve as a means of grouping objects and activities that share a // common originating context or purpose. An example could be all activities relating to a common project or event. Context Item `jsonld:"context,omitempty"` // EndTime the date and time describing the actual or expected ending time of the object. // When used with an Activity object, for instance, the endTime property specifies the moment // the activity concluded or is expected to conclude. EndTime time.Time `jsonld:"endTime,omitempty"` // Generator identifies the entity (e.g. an application) that generated the object. Generator Item `jsonld:"generator,omitempty"` // Icon indicates an entity that describes an icon for this object. // The image should have an aspect ratio of one (horizontal) to one (vertical) // and should be suitable for presentation at a small size. Icon Item `jsonld:"icon,omitempty"` // Image indicates an entity that describes an image for this object. // Unlike the icon property, there are no aspect ratio or display size limitations assumed. Image Item `jsonld:"image,omitempty"` // InReplyTo indicates one or more entities for which this object is considered a response. InReplyTo Item `jsonld:"inReplyTo,omitempty"` // Location indicates one or more physical or logical locations associated with the object. Location Item `jsonld:"location,omitempty"` // Preview identifies an entity that providesa preview of this object. Preview Item `jsonld:"preview,omitempty"` // Published the date and time at which the object was published Published time.Time `jsonld:"published,omitempty"` // Replies identifies a Collection containing objects considered to be responses to this object. Replies Item `jsonld:"replies,omitempty"` // StartTime the date and time describing the actual or expected starting time of the object. // When used with an Activity object, for instance, the startTime property specifies // the moment the activity began or is scheduled to begin. StartTime time.Time `jsonld:"startTime,omitempty"` // Summary a natural language summarization of the object encoded as HTML. // *Multiple language tagged summaries may be provided.) Summary NaturalLanguageValue `jsonld:"summary,omitempty,collapsible"` // Tag One or more "tags" that have been associated with an objects. A tag can be any kind of Activity Pub Object. // The key difference between attachment and tag is that the former implies association by inclusion, // while the latter implies associated by reference. Tag Item `jsonld:"tag,omitempty"` // Updated the date and time at which the object was updated Updated time.Time `jsonld:"updated,omitempty"` // URL identifies one or more links to representations of the object URL LinkOrURI `jsonld:"url,omitempty"` // To identifies an entity considered to be part of the public primary audience of an Activity Pub Object To ItemCollection `jsonld:"to,omitempty"` // Bto identifies an Activity Pub Object that is part of the private primary audience of this Activity Pub Object. Bto ItemCollection `jsonld:"bto,omitempty"` // CC identifies an Activity Pub Object that is part of the public secondary audience of this Activity Pub Object. CC ItemCollection `jsonld:"cc,omitempty"` // BCC identifies one or more Objects that are part of the private secondary audience of this Activity Pub Object. BCC ItemCollection `jsonld:"bcc,omitempty"` // Duration When the object describes a time-bound resource, such as an audio or video, a meeting, etc, // the duration property indicates the object's approximate duration. // The value must be expressed as an xsd:duration as defined by [ xmlschema11-2], // section 3.3.6 (e.g. a period of 5 seconds is represented as "PT5S"). Duration time.Duration `jsonld:"duration,omitempty"` // Actor describes one or more entities that either performed or are expected to perform the activity. // Any single activity can have multiple actors. The actor may be specified using an indirect Link. Actor Actor `jsonld:"actor,omitempty"` // Target describes the indirect object, or target, of the activity. // The precise meaning of the target is largely dependent on the type of action being described // but will often be the object of the English preposition "to". // For instance, in the activity "John added a movie to his wishlist", // the target of the activity is John's wishlist. An activity can have more than one target. Target Item `jsonld:"target,omitempty"` // Result describes the result of the activity. For instance, if a particular action results in the creation // of a new resource, the result property can be used to describe that new resource. Result Item `jsonld:"result,omitempty"` // Origin describes an indirect object of the activity from which the activity is directed. // The precise meaning of the origin is the object of the English preposition "from". // For instance, in the activity "John moved an item to List B from List A", the origin of the activity is "List A". Origin Item `jsonld:"origin,omitempty"` // Instrument identifies one or more objects used (or to be used) in the completion of an Activity. Instrument Item `jsonld:"instrument,omitempty"` // OneOf identifies an exclusive option for a Question. Use of oneOf implies that the Question // can have only a single answer. To indicate that a Question can have multiple answers, use anyOf. OneOf Item `jsonld:"oneOf,omitempty"` // AnyOf identifies an inclusive option for a Question. Use of anyOf implies that the Question can have multiple answers. // To indicate that a Question can have only one answer, use oneOf. AnyOf Item `jsonld:"anyOf,omitempty"` // Closed indicates that a question has been closed, and answers are no longer accepted. Closed bool `jsonld:"closed,omitempty"` } // AcceptNew initializes an Accept activity func AcceptNew(id ObjectID, ob Item) *Accept { a := ActivityNew(id, AcceptType, ob) o := Accept(*a) return &o } // AddNew initializes an Add activity func AddNew(id ObjectID, ob Item, trgt Item) *Add { a := ActivityNew(id, AddType, ob) o := Add(*a) o.Target = trgt return &o } // AnnounceNew initializes an Announce activity func AnnounceNew(id ObjectID, ob Item) *Announce { a := ActivityNew(id, AnnounceType, ob) o := Announce(*a) return &o } // ArriveNew initializes an Arrive activity func ArriveNew(id ObjectID) *Arrive { a := IntransitiveActivityNew(id, ArriveType) o := Arrive(*a) return &o } // BlockNew initializes a Block activity func BlockNew(id ObjectID, ob Item) *Block { a := ActivityNew(id, BlockType, ob) o := Block(*a) return &o } // CreateNew initializes a Create activity func CreateNew(id ObjectID, ob Item) *Create { a := ActivityNew(id, CreateType, ob) o := Create(*a) return &o } // DeleteNew initializes a Delete activity func DeleteNew(id ObjectID, ob Item) *Delete { a := ActivityNew(id, DeleteType, ob) o := Delete(*a) return &o } // DislikeNew initializes a Dislike activity func DislikeNew(id ObjectID, ob Item) *Dislike { a := ActivityNew(id, DislikeType, ob) o := Dislike(*a) return &o } // FlagNew initializes a Flag activity func FlagNew(id ObjectID, ob Item) *Flag { a := ActivityNew(id, FlagType, ob) o := Flag(*a) return &o } // FollowNew initializes a Follow activity func FollowNew(id ObjectID, ob Item) *Follow { a := ActivityNew(id, FollowType, ob) o := Follow(*a) return &o } // IgnoreNew initializes an Ignore activity func IgnoreNew(id ObjectID, ob Item) *Ignore { a := ActivityNew(id, IgnoreType, ob) o := Ignore(*a) return &o } // InviteNew initializes an Invite activity func InviteNew(id ObjectID, ob Item) *Invite { a := ActivityNew(id, InviteType, ob) o := Invite(*a) return &o } // JoinNew initializes a Join activity func JoinNew(id ObjectID, ob Item) *Join { a := ActivityNew(id, JoinType, ob) o := Join(*a) return &o } // LeaveNew initializes a Leave activity func LeaveNew(id ObjectID, ob Item) *Leave { a := ActivityNew(id, LeaveType, ob) o := Leave(*a) return &o } // LikeNew initializes a Like activity func LikeNew(id ObjectID, ob Item) *Like { a := ActivityNew(id, LikeType, ob) o := Like(*a) return &o } // ListenNew initializes a Listen activity func ListenNew(id ObjectID, ob Item) *Listen { a := ActivityNew(id, ListenType, ob) o := Listen(*a) return &o } // MoveNew initializes a Move activity func MoveNew(id ObjectID, ob Item) *Move { a := ActivityNew(id, MoveType, ob) o := Move(*a) return &o } // OfferNew initializes an Offer activity func OfferNew(id ObjectID, ob Item) *Offer { a := ActivityNew(id, OfferType, ob) o := Offer(*a) return &o } // RejectNew initializes a Reject activity func RejectNew(id ObjectID, ob Item) *Reject { a := ActivityNew(id, RejectType, ob) o := Reject(*a) return &o } // ReadNew initializes a Read activity func ReadNew(id ObjectID, ob Item) *Read { a := ActivityNew(id, ReadType, ob) o := Read(*a) return &o } // RemoveNew initializes a Remove activity func RemoveNew(id ObjectID, ob Item, trgt Item) *Remove { a := ActivityNew(id, RemoveType, ob) o := Remove(*a) o.Target = trgt return &o } // TentativeRejectNew initializes a TentativeReject activity func TentativeRejectNew(id ObjectID, ob Item) *TentativeReject { a := ActivityNew(id, TentativeRejectType, ob) o := TentativeReject(*a) return &o } // TentativeAcceptNew initializes a TentativeAccept activity func TentativeAcceptNew(id ObjectID, ob Item) *TentativeAccept { a := ActivityNew(id, TentativeAcceptType, ob) o := TentativeAccept(*a) return &o } // TravelNew initializes a Travel activity func TravelNew(id ObjectID) *Travel { a := IntransitiveActivityNew(id, TravelType) o := Travel(*a) return &o } // UndoNew initializes an Undo activity func UndoNew(id ObjectID, ob Item) *Undo { a := ActivityNew(id, UndoType, ob) o := Undo(*a) return &o } // UpdateNew initializes an Update activity func UpdateNew(id ObjectID, ob Item) *Update { a := ActivityNew(id, UpdateType, ob) u := Update(*a) return &u } // ViewNew initializes a View activity func ViewNew(id ObjectID, ob Item) *View { a := ActivityNew(id, ViewType, ob) o := View(*a) return &o } // QuestionNew initializes a Question activity func QuestionNew(id ObjectID) *Question { q := Question{ID: id, Type: QuestionType} q.Name = NaturalLanguageValueNew() q.Content = NaturalLanguageValueNew() return &q } // ValidContentManagementType is a validation function for content management Activity objects func ValidContentManagementType(typ ActivityVocabularyType) bool { for _, v := range validContentManagementActivityTypes { if v == typ { return true } } return false } // ValidCollectionManagementType is a validation function for collection management Activity objects func ValidCollectionManagementType(typ ActivityVocabularyType) bool { for _, v := range validCollectionManagementActivityTypes { if v == typ { return true } } return false } // ValidReactionsType is a validation function for reactions Activity objects func ValidReactionsType(typ ActivityVocabularyType) bool { for _, v := range validReactionsActivityTypes { if v == typ { return true } } return false } // ValidActivityType is a validation function for Activity objects func ValidActivityType(typ ActivityVocabularyType) bool { for _, v := range validActivityTypes { if v == typ { return true } } return false } // ValidIntransitiveActivityType is a validation function for IntransitiveActivity objects func ValidIntransitiveActivityType(typ ActivityVocabularyType) bool { for _, v := range validIntransitiveActivityTypes { if v == typ { return true } } return false } // ActivityNew initializes a basic activity func ActivityNew(id ObjectID, typ ActivityVocabularyType, ob Item) *Activity { if !ValidActivityType(typ) { typ = ActivityType } a := Activity{Parent: Parent{ID: id, Type: typ}} a.Name = NaturalLanguageValueNew() a.Content = NaturalLanguageValueNew() a.Object = ob return &a } // IntransitiveActivityNew initializes a intransitive activity func IntransitiveActivityNew(id ObjectID, typ ActivityVocabularyType) *IntransitiveActivity { if !ValidIntransitiveActivityType(typ) { typ = IntransitiveActivityType } i := IntransitiveActivity{Parent: Parent{ID: id, Type: typ}} i.Name = NaturalLanguageValueNew() i.Content = NaturalLanguageValueNew() return &i } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (a *Activity) RecipientsDeduplication() { var actor ItemCollection actor.Append(a.Actor) recipientsDeduplication(&actor, &a.To, &a.Bto, &a.CC, &a.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (i *IntransitiveActivity) RecipientsDeduplication() { var actor ItemCollection actor.Append(i.Actor) recipientsDeduplication(&actor, &i.To, &i.Bto, &i.CC, &i.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (b *Block) RecipientsDeduplication() { var dedupObjects ItemCollection dedupObjects.Append(b.Actor) dedupObjects.Append(b.Object) recipientsDeduplication(&dedupObjects, &b.To, &b.Bto, &b.CC, &b.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (c *Create) RecipientsDeduplication() { var dedupObjects ItemCollection dedupObjects.Append(c.Actor) dedupObjects.Append(c.Object) recipientsDeduplication(&dedupObjects, &c.To, &c.Bto, &c.CC, &c.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (l *Like) RecipientsDeduplication() { var dedupObjects ItemCollection dedupObjects.Append(l.Actor) dedupObjects.Append(l.Object) recipientsDeduplication(&dedupObjects, &l.To, &l.Bto, &l.CC, &l.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (d *Dislike) RecipientsDeduplication() { var dedupObjects ItemCollection dedupObjects.Append(d.Actor) dedupObjects.Append(d.Object) recipientsDeduplication(&dedupObjects, &d.To, &d.Bto, &d.CC, &d.BCC) } // RecipientsDeduplication performs recipient de-duplication on the Activity's To, Bto, CC and BCC properties func (u *Update) RecipientsDeduplication() { var dedupObjects ItemCollection dedupObjects.Append(u.Actor) dedupObjects.Append(u.Object) recipientsDeduplication(&dedupObjects, &u.To, &u.Bto, &u.CC, &u.BCC) } // GetType returns the ActivityVocabulary type of the current Intransitive Activity func (i IntransitiveActivity) GetType() ActivityVocabularyType { return i.Type } // IsLink returns false for Activity objects func (i IntransitiveActivity) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the IntransitiveActivity object func (i IntransitiveActivity) GetID() *ObjectID { return &i.ID } // GetLink returns the IRI corresponding to the IntransitiveActivity object func (i IntransitiveActivity) GetLink() IRI { return IRI(i.ID) } // IsObject returns true for Activity objects func (i IntransitiveActivity) IsObject() bool { return true } // GetType returns the ActivityVocabulary type of the current Activity func (a Activity) GetType() ActivityVocabularyType { return a.Type } // IsLink returns false for Activity objects func (a Activity) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Activity object func (a Activity) GetID() *ObjectID { return &a.ID } // GetLink returns the IRI corresponding to the Activity object func (a Activity) GetLink() IRI { return IRI(a.ID) } // IsObject returns true for Activity objects func (a Activity) IsObject() bool { return true } // GetID returns the ObjectID corresponding to the Like object func (l Like) GetID() *ObjectID { return Activity(l).GetID() } // GetLink returns the IRI corresponding to the Like object func (l Like) GetLink() IRI { return IRI(l.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (l Like) GetType() ActivityVocabularyType { return l.Type } // IsObject returns true for Like objects func (l Like) IsObject() bool { return true } // IsLink returns false for Like objects func (l Like) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Dislike object func (d Dislike) GetID() *ObjectID { return Activity(d).GetID() } // GetLink returns the IRI corresponding to the Dislike object func (d Dislike) GetLink() IRI { return IRI(d.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (d Dislike) GetType() ActivityVocabularyType { return d.Type } // IsObject returns true for Dislike objects func (d Dislike) IsObject() bool { return true } // IsLink returns false for Dislike objects func (d Dislike) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Accept object func (a Accept) GetID() *ObjectID { return Activity(a).GetID() } // GetLink returns the IRI corresponding to the Accept object func (a Accept) GetLink() IRI { return IRI(a.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (a Accept) GetType() ActivityVocabularyType { return a.Type } // IsObject returns true for Accept objects func (a Accept) IsObject() bool { return true } // IsLink returns false for Accept objects func (a Accept) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Add object func (a Add) GetID() *ObjectID { return Activity(a).GetID() } // GetLink returns the IRI corresponding to the Add object func (a Add) GetLink() IRI { return IRI(a.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (a Add) GetType() ActivityVocabularyType { return a.Type } // IsObject returns true for Add objects func (a Add) IsObject() bool { return true } // IsLink returns false for Add objects func (a Add) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Announce object func (a Announce) GetID() *ObjectID { return Activity(a).GetID() } // GetLink returns the IRI corresponding to the Announce object func (a Announce) GetLink() IRI { return IRI(a.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (a Announce) GetType() ActivityVocabularyType { return a.Type } // IsObject returns true for Announce objects func (a Announce) IsObject() bool { return true } // IsLink returns false for Announce objects func (a Announce) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Arrive object func (a Arrive) GetID() *ObjectID { return IntransitiveActivity(a).GetID() } // GetLink returns the IRI corresponding to the Arrive object func (a Arrive) GetLink() IRI { return IRI(a.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (a Arrive) GetType() ActivityVocabularyType { return a.Type } // IsObject returns true for Arrive objects func (a Arrive) IsObject() bool { return true } // IsLink returns false for Arrive objects func (a Arrive) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Block object func (b Block) GetID() *ObjectID { return Activity(b).GetID() } // GetLink returns the IRI corresponding to the Block object func (b Block) GetLink() IRI { return IRI(b.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (b Block) GetType() ActivityVocabularyType { return b.Type } // IsObject returns true for Block objects func (b Block) IsObject() bool { return true } // IsLink returns false for Block objects func (b Block) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Create object func (c Create) GetID() *ObjectID { return Activity(c).GetID() } // GetLink returns the IRI corresponding to the Create object func (c Create) GetLink() IRI { return IRI(c.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (c Create) GetType() ActivityVocabularyType { return c.Type } // IsObject returns true for Create objects func (c Create) IsObject() bool { return true } // IsLink returns false for Create objects func (c Create) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Delete object func (d Delete) GetID() *ObjectID { return Activity(d).GetID() } // GetLink returns the IRI corresponding to the Delete object func (d Delete) GetLink() IRI { return IRI(d.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (d Delete) GetType() ActivityVocabularyType { return d.Type } // IsObject returns true for Delete objects func (d Delete) IsObject() bool { return true } // IsLink returns false for Delete objects func (d Delete) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Flag object func (f Flag) GetID() *ObjectID { return Activity(f).GetID() } // GetLink returns the IRI corresponding to the Flag object func (f Flag) GetLink() IRI { return IRI(f.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (f Flag) GetType() ActivityVocabularyType { return f.Type } // IsObject returns true for Flag objects func (f Flag) IsObject() bool { return true } // IsLink returns false for Flag objects func (f Flag) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Follow object func (f Follow) GetID() *ObjectID { return Activity(f).GetID() } // GetLink returns the IRI corresponding to the Follow object func (f Follow) GetLink() IRI { return IRI(f.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (f Follow) GetType() ActivityVocabularyType { return f.Type } // IsObject returns true for Follow objects func (f Follow) IsObject() bool { return true } // IsLink returns false for Follow objects func (f Follow) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Ignore object func (i Ignore) GetID() *ObjectID { return Activity(i).GetID() } // GetLink returns the IRI corresponding to the Ignore object func (i Ignore) GetLink() IRI { return IRI(i.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (i Ignore) GetType() ActivityVocabularyType { return i.Type } // IsObject returns true for Ignore objects func (i Ignore) IsObject() bool { return true } // IsLink returns false for Ignore objects func (i Ignore) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Invite object func (i Invite) GetID() *ObjectID { return Activity(i).GetID() } // GetLink returns the IRI corresponding to the Invite object func (i Invite) GetLink() IRI { return IRI(i.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (i Invite) GetType() ActivityVocabularyType { return i.Type } // IsObject returns true for Invite objects func (i Invite) IsObject() bool { return true } // IsLink returns false for Invite objects func (i Invite) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Join object func (j Join) GetID() *ObjectID { return Activity(j).GetID() } // GetLink returns the IRI corresponding to the Join object func (j Join) GetLink() IRI { return IRI(j.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (j Join) GetType() ActivityVocabularyType { return j.Type } // IsObject returns true for Join objects func (j Join) IsObject() bool { return true } // IsLink returns false for Join objects func (j Join) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Leave object func (l Leave) GetID() *ObjectID { return Activity(l).GetID() } // GetLink returns the IRI corresponding to the Leave object func (l Leave) GetLink() IRI { return IRI(l.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (l Leave) GetType() ActivityVocabularyType { return l.Type } // IsObject returns true for Leave objects func (l Leave) IsObject() bool { return true } // IsLink returns false for Leave objects func (l Leave) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Listen object func (l Listen) GetID() *ObjectID { return Activity(l).GetID() } // GetLink returns the IRI corresponding to the Listen object func (l Listen) GetLink() IRI { return IRI(l.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (l Listen) GetType() ActivityVocabularyType { return l.Type } // IsObject returns true for Listen objects func (l Listen) IsObject() bool { return true } // IsLink returns false for Listen objects func (l Listen) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Move object func (m Move) GetID() *ObjectID { return Activity(m).GetID() } // GetLink returns the IRI corresponding to the Move object func (m Move) GetLink() IRI { return IRI(m.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (m Move) GetType() ActivityVocabularyType { return m.Type } // IsObject returns true for Move objects func (m Move) IsObject() bool { return true } // IsLink returns false for Move objects func (m Move) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Offer object func (o Offer) GetID() *ObjectID { return Activity(o).GetID() } // GetLink returns the IRI corresponding to the Offer object func (o Offer) GetLink() IRI { return IRI(o.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (o Offer) GetType() ActivityVocabularyType { return o.Type } // IsObject returns true for Offer objects func (o Offer) IsObject() bool { return true } // IsLink returns false for Offer objects func (o Offer) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Question object func (q Question) GetID() *ObjectID { return &q.ID } // GetLink returns the IRI corresponding to the Question object func (q Question) GetLink() IRI { return IRI(q.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (q Question) GetType() ActivityVocabularyType { return q.Type } // IsObject returns true for Question objects func (q Question) IsObject() bool { return true } // IsLink returns false for Question objects func (q Question) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Reject object func (r Reject) GetID() *ObjectID { return Activity(r).GetID() } // GetLink returns the IRI corresponding to the Reject object func (r Reject) GetLink() IRI { return IRI(r.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (r Reject) GetType() ActivityVocabularyType { return r.Type } // IsObject returns true for Reject objects func (r Reject) IsObject() bool { return true } // IsLink returns false for Reject objects func (r Reject) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Remove object func (r Remove) GetID() *ObjectID { return Activity(r).GetID() } // GetLink returns the IRI corresponding to the Remove object func (r Remove) GetLink() IRI { return IRI(r.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (r Remove) GetType() ActivityVocabularyType { return r.Type } // IsObject returns true for Remove objects func (r Remove) IsObject() bool { return true } // IsLink returns false for Remove objects func (r Remove) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Read object func (r Read) GetID() *ObjectID { return Activity(r).GetID() } // GetLink returns the IRI corresponding to the Read object func (r Read) GetLink() IRI { return IRI(r.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (r Read) GetType() ActivityVocabularyType { return r.Type } // IsObject returns true for Read objects func (r Read) IsObject() bool { return true } // IsLink returns false for Read objects func (r Read) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the TentativeAccept object func (t TentativeAccept) GetID() *ObjectID { return Activity(t).GetID() } // GetLink returns the IRI corresponding to the TentativeAccept object func (t TentativeAccept) GetLink() IRI { return IRI(t.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (t TentativeAccept) GetType() ActivityVocabularyType { return t.Type } // IsObject returns true for TentativeAccept objects func (t TentativeAccept) IsObject() bool { return true } // IsLink returns false for TentativeAccept objects func (t TentativeAccept) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the TentativeReject object func (t TentativeReject) GetID() *ObjectID { return Activity(t).GetID() } // GetLink returns the IRI corresponding to the TentativeReject object func (t TentativeReject) GetLink() IRI { return IRI(t.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (t TentativeReject) GetType() ActivityVocabularyType { return t.Type } // IsObject returns true for TentativeReject objects func (t TentativeReject) IsObject() bool { return true } // IsLink returns false for TentativeReject objects func (t TentativeReject) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Travel object func (t Travel) GetID() *ObjectID { return IntransitiveActivity(t).GetID() } // GetLink returns the IRI corresponding to the Travel object func (t Travel) GetLink() IRI { return IRI(t.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (t Travel) GetType() ActivityVocabularyType { return t.Type } // IsObject returns true for Travel objects func (t Travel) IsObject() bool { return true } // IsLink returns false for Travel objects func (t Travel) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Undo object func (u Undo) GetID() *ObjectID { return Activity(u).GetID() } // GetLink returns the IRI corresponding to the Unto object func (u Undo) GetLink() IRI { return IRI(u.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (u Undo) GetType() ActivityVocabularyType { return u.Type } // IsObject returns true for Undo objects func (u Undo) IsObject() bool { return true } // IsLink returns false for Undo objects func (u Undo) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Update object func (u Update) GetID() *ObjectID { return Activity(u).GetID() } // GetLink returns the IRI corresponding to the Update object func (u Update) GetLink() IRI { return IRI(u.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (u Update) GetType() ActivityVocabularyType { return u.Type } // IsObject returns true for Update objects func (u Update) IsObject() bool { return true } // IsLink returns false for Update objects func (u Update) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the View object func (v View) GetID() *ObjectID { return Activity(v).GetID() } // GetLink returns the IRI corresponding to the View object func (v View) GetLink() IRI { return IRI(v.ID) } // GetType returns the ActivityVocabulary type of the current Activity func (v View) GetType() ActivityVocabularyType { return v.Type } // IsObject returns true for View objects func (v View) IsObject() bool { return true } // IsLink returns false for View objects func (v View) IsLink() bool { return false } // UnmarshalJSON func (a *Activity) UnmarshalJSON(data []byte) error { a.Parent.UnmarshalJSON(data) a.Actor = getAPItem(data, "actor") a.Object = getAPItem(data, "object") return nil } // UnmarshalJSON func (l *Like) UnmarshalJSON(data []byte) error { a := Activity(*l) err := a.UnmarshalJSON(data) *l = Like(a) return err } // UnmarshalJSON func (d *Dislike) UnmarshalJSON(data []byte) error { a := Activity(*d) err := a.UnmarshalJSON(data) *d = Dislike(a) return err } // UnmarshalJSON func (u *Update) UnmarshalJSON(data []byte) error { a := Activity(*u) err := a.UnmarshalJSON(data) *u = Update(a) return err } // UnmarshalJSON func (c *Create) UnmarshalJSON(data []byte) error { a := Activity(*c) err := a.UnmarshalJSON(data) *c = Create(a) return err }
-
-
activitystreams/activity_test.go (deleted)
-
@@ -1,2354 +0,0 @@package activitystreams import ( "fmt" "testing" ) func TestActivityNew(t *testing.T) { var testValue = ObjectID("test") var testType ActivityVocabularyType = "Accept" a := ActivityNew(testValue, testType, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != testType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, testType) } g := ActivityNew(testValue, "", nil) if g.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", g.ID, testValue) } if g.Type != ActivityType { t.Errorf("Activity Type '%v' different than expected '%v'", g.Type, ActivityType) } } func TestIntransitiveActivityNew(t *testing.T) { var testValue = ObjectID("test") var testType ActivityVocabularyType = "Arrive" a := IntransitiveActivityNew(testValue, testType) if a.ID != testValue { t.Errorf("IntransitiveActivity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != testType { t.Errorf("IntransitiveActivity Type '%v' different than expected '%v'", a.Type, testType) } g := IntransitiveActivityNew(testValue, "") if g.ID != testValue { t.Errorf("IntransitiveActivity Id '%v' different than expected '%v'", g.ID, testValue) } if g.Type != IntransitiveActivityType { t.Errorf("IntransitiveActivity Type '%v' different than expected '%v'", g.Type, IntransitiveActivityType) } } func TestValidActivityType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidActivityType(ActivityType) { t.Errorf("Generic Activity Type '%v' should not be valid", ActivityType) } for _, inValidType := range validObjectTypes { if ValidActivityType(inValidType) { t.Errorf("APObject Type '%v' should be invalid", inValidType) } } if ValidActivityType(invalidType) { t.Errorf("Activity Type '%v' should not be valid", invalidType) } for _, validType := range validActivityTypes { if !ValidActivityType(validType) { t.Errorf("Activity Type '%v' should be valid", validType) } } } func TestValidIntransitiveActivityType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidIntransitiveActivityType(ActivityType) { t.Errorf("Generic Activity Type '%v' should not be valid", ActivityType) } for _, inValidType := range validActivityTypes { if ValidIntransitiveActivityType(inValidType) { t.Errorf("APObject Type '%v' should be invalid", inValidType) } } if ValidIntransitiveActivityType(invalidType) { t.Errorf("Activity Type '%v' should not be valid", invalidType) } for _, validType := range validIntransitiveActivityTypes { if !ValidIntransitiveActivityType(validType) { t.Errorf("Activity Type '%v' should be valid", validType) } } } func TestValidCollectionManagementType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidActivityType(ActivityType) { t.Errorf("Generic Activity Type '%v' should not be valid", ActivityType) } for _, inValidType := range validCollectionManagementActivityTypes { if !ValidCollectionManagementType(inValidType) { t.Errorf("APObject Type '%v' should be valid", inValidType) } } if ValidCollectionManagementType(invalidType) { t.Errorf("Activity Type '%v' should not be valid", invalidType) } for _, validType := range validContentManagementActivityTypes { if ValidCollectionManagementType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } for _, validType := range validReactionsActivityTypes { if ValidCollectionManagementType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } } func TestValidContentManagementType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidActivityType(ActivityType) { t.Errorf("Generic Activity Type '%v' should not be valid", ActivityType) } for _, inValidType := range validContentManagementActivityTypes { if !ValidContentManagementType(inValidType) { t.Errorf("APObject Type '%v' should be valid", inValidType) } } if ValidContentManagementType(invalidType) { t.Errorf("Activity Type '%v' should not be valid", invalidType) } for _, validType := range validCollectionManagementActivityTypes { if ValidContentManagementType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } for _, validType := range validReactionsActivityTypes { if ValidContentManagementType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } } func TestValidReactionsType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidReactionsType(ActivityType) { t.Errorf("Generic Activity Type '%v' should not be valid", ActivityType) } for _, inValidType := range validReactionsActivityTypes { if !ValidReactionsType(inValidType) { t.Errorf("APObject Type '%v' should be valid", inValidType) } } if ValidReactionsType(invalidType) { t.Errorf("Activity Type '%v' should not be valid", invalidType) } for _, validType := range validCollectionManagementActivityTypes { if ValidReactionsType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } for _, validType := range validContentManagementActivityTypes { if ValidReactionsType(validType) { t.Errorf("Activity Type '%v' should not be valid", validType) } } } func TestAcceptNew(t *testing.T) { var testValue = ObjectID("test") a := AcceptNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != AcceptType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, AcceptType) } } func TestAddNew(t *testing.T) { var testValue = ObjectID("test") a := AddNew(testValue, nil, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != AddType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, AddType) } } func TestAnnounceNew(t *testing.T) { var testValue = ObjectID("test") a := AnnounceNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != AnnounceType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, AnnounceType) } } func TestArriveNew(t *testing.T) { var testValue = ObjectID("test") a := ArriveNew(testValue) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != ArriveType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, ArriveType) } } func TestBlockNew(t *testing.T) { var testValue = ObjectID("test") a := BlockNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != BlockType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, BlockType) } } func TestCreateNew(t *testing.T) { var testValue = ObjectID("test") a := CreateNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != CreateType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, CreateType) } } func TestDeleteNew(t *testing.T) { var testValue = ObjectID("test") a := DeleteNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != DeleteType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, DeleteType) } } func TestDislikeNew(t *testing.T) { var testValue = ObjectID("test") a := DislikeNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != DislikeType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, DislikeType) } } func TestFlagNew(t *testing.T) { var testValue = ObjectID("test") a := FlagNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != FlagType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, FlagType) } } func TestFollowNew(t *testing.T) { var testValue = ObjectID("test") a := FollowNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != FollowType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, FollowType) } } func TestIgnoreNew(t *testing.T) { var testValue = ObjectID("test") a := IgnoreNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != IgnoreType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, IgnoreType) } } func TestInviteNew(t *testing.T) { var testValue = ObjectID("test") a := InviteNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != InviteType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, InviteType) } } func TestJoinNew(t *testing.T) { var testValue = ObjectID("test") a := JoinNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != JoinType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, JoinType) } } func TestLeaveNew(t *testing.T) { var testValue = ObjectID("test") a := LeaveNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != LeaveType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, LeaveType) } } func TestLikeNew(t *testing.T) { var testValue = ObjectID("test") a := LikeNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != LikeType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, LikeType) } } func TestListenNew(t *testing.T) { var testValue = ObjectID("test") a := ListenNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != ListenType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, ListenType) } } func TestMoveNew(t *testing.T) { var testValue = ObjectID("test") a := MoveNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != MoveType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, MoveType) } } func TestOfferNew(t *testing.T) { var testValue = ObjectID("test") a := OfferNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != OfferType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, OfferType) } } func TestQuestionNew(t *testing.T) { var testValue = ObjectID("test") a := QuestionNew(testValue) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != QuestionType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, QuestionType) } } func TestRejectNew(t *testing.T) { var testValue = ObjectID("test") a := RejectNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != RejectType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, RejectType) } } func TestReadNew(t *testing.T) { var testValue = ObjectID("test") a := ReadNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != ReadType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, ReadType) } } func TestRemoveNew(t *testing.T) { var testValue = ObjectID("test") a := RemoveNew(testValue, nil, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != RemoveType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, RemoveType) } } func TestTentativeRejectNew(t *testing.T) { var testValue = ObjectID("test") a := TentativeRejectNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != TentativeRejectType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, TentativeRejectType) } } func TestTentativeAcceptNew(t *testing.T) { var testValue = ObjectID("test") a := TentativeAcceptNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != TentativeAcceptType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, TentativeAcceptType) } } func TestTravelNew(t *testing.T) { var testValue = ObjectID("test") a := TravelNew(testValue) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != TravelType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, TravelType) } } func TestUndoNew(t *testing.T) { var testValue = ObjectID("test") a := UndoNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != UndoType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, UndoType) } } func TestUpdateNew(t *testing.T) { var testValue = ObjectID("test") a := UpdateNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != UpdateType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, UpdateType) } } func TestViewNew(t *testing.T) { var testValue = ObjectID("test") a := ViewNew(testValue, nil) if a.ID != testValue { t.Errorf("Activity Id '%v' different than expected '%v'", a.ID, testValue) } if a.Type != ViewType { t.Errorf("Activity Type '%v' different than expected '%v'", a.Type, ViewType) } } func TestActivityRecipientsDeduplication(t *testing.T) { bob := PersonNew("bob") alice := PersonNew("alice") foo := OrganizationNew("foo") bar := GroupNew("bar") a := ActivityNew("t", "test", nil) a.To.Append(bob) a.To.Append(alice) a.To.Append(foo) a.To.Append(bar) if len(a.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", a, len(a.To)) } a.To.Append(bar) a.To.Append(alice) a.To.Append(foo) a.To.Append(bob) if len(a.To) != 8 { t.Errorf("%T.To should have exactly 8(eight) elements, not %d", a, len(a.To)) } a.RecipientsDeduplication() if len(a.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", a, len(a.To)) } b := ActivityNew("t", "test", nil) b.To.Append(bar) b.To.Append(alice) b.To.Append(foo) b.To.Append(bob) b.Bto.Append(bar) b.Bto.Append(alice) b.Bto.Append(foo) b.Bto.Append(bob) b.CC.Append(bar) b.CC.Append(alice) b.CC.Append(foo) b.CC.Append(bob) b.BCC.Append(bar) b.BCC.Append(alice) b.BCC.Append(foo) b.BCC.Append(bob) b.RecipientsDeduplication() if len(b.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", b, len(b.To)) } if len(b.Bto) != 0 { t.Errorf("%T.Bto should have exactly 0(zero) elements, not %d", b, len(b.Bto)) } if len(b.CC) != 0 { t.Errorf("%T.CC should have exactly 0(zero) elements, not %d", b, len(b.CC)) } if len(b.BCC) != 0 { t.Errorf("%T.BCC should have exactly 0(zero) elements, not %d", b, len(b.BCC)) } } func TestBlockRecipientsDeduplication(t *testing.T) { bob := PersonNew("bob") alice := PersonNew("alice") foo := OrganizationNew("foo") bar := GroupNew("bar") a := BlockNew("bbb", bob) a.To.Append(bob) a.To.Append(alice) a.To.Append(foo) a.To.Append(bar) if len(a.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", a, len(a.To)) } a.To.Append(bar) a.To.Append(alice) a.To.Append(foo) a.To.Append(bob) if len(a.To) != 8 { t.Errorf("%T.To should have exactly 8(eight) elements, not %d", a, len(a.To)) } a.RecipientsDeduplication() if len(a.To) != 3 { t.Errorf("%T.To should have exactly 3(four) elements, not %d", a, len(a.To)) } b := BlockNew("t", bob) b.To.Append(bar) b.To.Append(alice) b.To.Append(foo) b.To.Append(bob) b.Bto.Append(bar) b.Bto.Append(alice) b.Bto.Append(foo) b.Bto.Append(bob) b.CC.Append(bar) b.CC.Append(alice) b.CC.Append(foo) b.CC.Append(bob) b.BCC.Append(bar) b.BCC.Append(alice) b.BCC.Append(foo) b.BCC.Append(bob) b.RecipientsDeduplication() if len(b.To) != 3 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", b, len(b.To)) } if len(b.Bto) != 0 { t.Errorf("%T.Bto should have exactly 0(zero) elements, not %d", b, len(b.Bto)) } if len(b.CC) != 0 { t.Errorf("%T.CC should have exactly 0(zero) elements, not %d", b, len(b.CC)) } if len(b.BCC) != 0 { t.Errorf("%T.BCC should have exactly 0(zero) elements, not %d", b, len(b.BCC)) } var err error recIds := make([]ObjectID, 0) err = checkDedup(b.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.BCC, &recIds) if err != nil { t.Error(err) } } func TestIntransitiveActivityRecipientsDeduplication(t *testing.T) { bob := PersonNew("bob") alice := PersonNew("alice") foo := OrganizationNew("foo") bar := GroupNew("bar") a := IntransitiveActivityNew("test", "t") a.To.Append(bob) a.To.Append(alice) a.To.Append(foo) a.To.Append(bar) if len(a.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", a, len(a.To)) } a.To.Append(bar) a.To.Append(alice) a.To.Append(foo) a.To.Append(bob) if len(a.To) != 8 { t.Errorf("%T.To should have exactly 8(eight) elements, not %d", a, len(a.To)) } a.RecipientsDeduplication() if len(a.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", a, len(a.To)) } b := ActivityNew("t", "test", nil) b.To.Append(bar) b.To.Append(alice) b.To.Append(foo) b.To.Append(bob) b.Bto.Append(bar) b.Bto.Append(alice) b.Bto.Append(foo) b.Bto.Append(bob) b.CC.Append(bar) b.CC.Append(alice) b.CC.Append(foo) b.CC.Append(bob) b.BCC.Append(bar) b.BCC.Append(alice) b.BCC.Append(foo) b.BCC.Append(bob) b.RecipientsDeduplication() if len(b.To) != 4 { t.Errorf("%T.To should have exactly 4(four) elements, not %d", b, len(b.To)) } if len(b.Bto) != 0 { t.Errorf("%T.Bto should have exactly 0(zero) elements, not %d", b, len(b.Bto)) } if len(b.CC) != 0 { t.Errorf("%T.CC should have exactly 0(zero) elements, not %d", b, len(b.CC)) } if len(b.BCC) != 0 { t.Errorf("%T.BCC should have exactly 0(zero) elements, not %d", b, len(b.BCC)) } var err error recIds := make([]ObjectID, 0) err = checkDedup(b.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.BCC, &recIds) if err != nil { t.Error(err) } } func TestCreate_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" c := CreateNew("act", o) c.To.Append(to) c.CC.Append(cc) c.BCC.Append(cc) c.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(c.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.BCC, &recIds) if err != nil { t.Error(err) } } func TestDislike_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" d := DislikeNew("act", o) d.To.Append(to) d.CC.Append(cc) d.BCC.Append(cc) d.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(d.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(d.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(d.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(d.BCC, &recIds) if err != nil { t.Error(err) } } func TestLike_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" l := LikeNew("act", o) l.To.Append(to) l.CC.Append(cc) l.BCC.Append(cc) l.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(l.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(l.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(l.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(l.BCC, &recIds) if err != nil { t.Error(err) } } func TestUpdate_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" u := UpdateNew("act", o) u.To.Append(to) u.CC.Append(cc) u.BCC.Append(cc) u.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(u.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(u.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(u.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(u.BCC, &recIds) if err != nil { t.Error(err) } } func TestActivity_GetID(t *testing.T) { a := ActivityNew("test", ActivityType, Person{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestActivity_GetIDGetType(t *testing.T) { a := ActivityNew("test", ActivityType, Person{}) if *a.GetID() != "test" || a.GetType() != ActivityType { t.Errorf("%T should not return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestActivity_IsLink(t *testing.T) { a := ActivityNew("test", ActivityType, Person{}) if a.IsLink() { t.Errorf("%T should not respond true to IsLink", a) } } func TestActivity_IsObject(t *testing.T) { a := ActivityNew("test", ActivityType, Person{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestIntransitiveActivity_GetLink(t *testing.T) { i := IntransitiveActivityNew("test", QuestionType) if *i.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", i, i, i) } } func TestIntransitiveActivity_GetObject(t *testing.T) { i := IntransitiveActivityNew("test", QuestionType) if *i.GetID() != "test" || i.GetType() != QuestionType { t.Errorf("%T should not return an empty %T object. Received %#v", i, i, i) } } func TestIntransitiveActivity_IsLink(t *testing.T) { i := IntransitiveActivityNew("test", QuestionType) if i.IsLink() { t.Errorf("%T should not respond true to IsLink", i) } } func TestIntransitiveActivity_IsObject(t *testing.T) { i := IntransitiveActivityNew("test", ActivityType) if !i.IsObject() { t.Errorf("%T should respond true to IsObject", i) } } func checkDedup(list ItemCollection, recIds *[]ObjectID) error { for _, rec := range list { for _, id := range *recIds { if *rec.GetID() == id { return fmt.Errorf("%T[%s] already stored in recipients list, Deduplication faild", rec, id) } } *recIds = append(*recIds, *rec.GetID()) } return nil } func TestActivity_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" c := ActivityNew("act", ActivityType, o) c.To.Append(to) c.CC.Append(cc) c.BCC.Append(cc) c.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(c.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.BCC, &recIds) if err != nil { t.Error(err) } } func TestIntransitiveActivity_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" c := IntransitiveActivityNew("act", IntransitiveActivityType) c.To.Append(to) c.CC.Append(cc) c.BCC.Append(cc) c.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(c.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(c.BCC, &recIds) if err != nil { t.Error(err) } } func TestBlock_RecipientsDeduplication(t *testing.T) { to := PersonNew("bob") o := ObjectNew(ArticleType) cc := PersonNew("alice") o.ID = "something" b := BlockNew("act", o) b.To.Append(to) b.CC.Append(cc) b.BCC.Append(cc) b.RecipientsDeduplication() var err error recIds := make([]ObjectID, 0) err = checkDedup(b.To, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.Bto, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.CC, &recIds) if err != nil { t.Error(err) } err = checkDedup(b.BCC, &recIds) if err != nil { t.Error(err) } } func TestRead_GetID(t *testing.T) { a := ReadNew("test", Person{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestAccept_GetID(t *testing.T) { a := AcceptNew("test", Person{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestAdd_GetID(t *testing.T) { a := AddNew("test", Person{}, Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), a) } } func TestAnnounce_GetID(t *testing.T) { a := AnnounceNew("test", Person{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestArrive_GetID(t *testing.T) { a := ArriveNew("test") if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestBlock_GetID(t *testing.T) { a := BlockNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestCreate_GetID(t *testing.T) { a := CreateNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestDelete_GetID(t *testing.T) { a := DeleteNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestDislike_GetID(t *testing.T) { a := DislikeNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestFlag_GetID(t *testing.T) { a := FlagNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestFollow_GetID(t *testing.T) { a := FollowNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestIgnore_GetID(t *testing.T) { a := IgnoreNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestInvite_GetID(t *testing.T) { a := InviteNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestJoin_GetID(t *testing.T) { a := JoinNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestLeave_GetID(t *testing.T) { a := LeaveNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestLike_GetID(t *testing.T) { a := LikeNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestListen_GetID(t *testing.T) { a := ListenNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestMove_GetID(t *testing.T) { a := MoveNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestOffer_GetID(t *testing.T) { a := OfferNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestQuestion_GetID(t *testing.T) { a := QuestionNew("test") if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestReject_GetID(t *testing.T) { a := RejectNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestRemove_GetID(t *testing.T) { a := RemoveNew("test", Object{}, Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestTravel_GetID(t *testing.T) { a := TravelNew("test") if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestUndo_GetID(t *testing.T) { a := UndoNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestUpdate_GetID(t *testing.T) { a := UpdateNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestView_GetID(t *testing.T) { a := ViewNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestIntransitiveActivity_GetID(t *testing.T) { a := IntransitiveActivityNew("test", IntransitiveActivityType) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestTentativeAccept_GetID(t *testing.T) { a := TentativeAcceptNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestTentativeReject_GetID(t *testing.T) { a := TentativeRejectNew("test", Object{}) if *a.GetID() != "test" { t.Errorf("%T should return an empty %T object. Received %#v", a, a.GetID(), *a.GetID()) } } func TestAccept_IsObject(t *testing.T) { a := AcceptNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestAdd_IsObject(t *testing.T) { a := AddNew("test", Object{}, Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestAnnounce_IsObject(t *testing.T) { a := AnnounceNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestArrive_IsObject(t *testing.T) { a := ArriveNew("test") if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestBlock_IsObject(t *testing.T) { a := BlockNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestCreate_IsObject(t *testing.T) { a := CreateNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestDelete_IsObject(t *testing.T) { a := DeleteNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestDislike_IsObject(t *testing.T) { a := DislikeNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestFlag_IsObject(t *testing.T) { a := FlagNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestFollow_IsObject(t *testing.T) { a := FollowNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestIgnore_IsObject(t *testing.T) { a := IgnoreNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestInvite_IsObject(t *testing.T) { a := InviteNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestJoin_IsObject(t *testing.T) { a := JoinNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestLeave_IsObject(t *testing.T) { a := LeaveNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestLike_IsObject(t *testing.T) { a := LikeNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestListen_IsObject(t *testing.T) { a := ListenNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestMove_IsObject(t *testing.T) { a := MoveNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestOffer_IsObject(t *testing.T) { a := OfferNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestQuestion_IsObject(t *testing.T) { a := QuestionNew("test") if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestRead_IsObject(t *testing.T) { a := ReadNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestReject_IsObject(t *testing.T) { a := RejectNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestRemove_IsObject(t *testing.T) { a := RemoveNew("test", Object{}, Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestTravel_IsObject(t *testing.T) { a := TravelNew("test") if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestUndo_IsObject(t *testing.T) { a := UndoNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestUpdate_IsObject(t *testing.T) { a := UpdateNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestView_IsObject(t *testing.T) { a := ViewNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestTentativeAccept_IsObject(t *testing.T) { a := TentativeAcceptNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestTentativeReject_IsObject(t *testing.T) { a := TentativeRejectNew("test", Object{}) if !a.IsObject() { t.Errorf("%T should respond true to IsObject", a) } } func TestAccept_IsLink(t *testing.T) { a := AcceptNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestAdd_IsLink(t *testing.T) { a := AddNew("test", Object{}, Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestAnnounce_IsLink(t *testing.T) { a := AnnounceNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestArrive_IsLink(t *testing.T) { a := ArriveNew("test") if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestBlock_IsLink(t *testing.T) { a := BlockNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestCreate_IsLink(t *testing.T) { a := CreateNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestDelete_IsLink(t *testing.T) { a := DeleteNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestDislike_IsLink(t *testing.T) { a := DislikeNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestFlag_IsLink(t *testing.T) { a := FlagNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestFollow_IsLink(t *testing.T) { a := FollowNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestIgnore_IsLink(t *testing.T) { a := IgnoreNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestInvite_IsLink(t *testing.T) { a := InviteNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestJoin_IsLink(t *testing.T) { a := JoinNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestLeave_IsLink(t *testing.T) { a := LeaveNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestLike_IsLink(t *testing.T) { a := LikeNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestListen_IsLink(t *testing.T) { a := ListenNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestMove_IsLink(t *testing.T) { a := MoveNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestOffer_IsLink(t *testing.T) { a := OfferNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestQuestion_IsLink(t *testing.T) { a := QuestionNew("test") if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestRead_IsLink(t *testing.T) { a := ReadNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestReject_IsLink(t *testing.T) { a := RejectNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestRemove_IsLink(t *testing.T) { a := RemoveNew("test", Object{}, Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestTravel_IsLink(t *testing.T) { a := TravelNew("test") if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestUndo_IsLink(t *testing.T) { a := UndoNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestUpdate_IsLink(t *testing.T) { a := UpdateNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestView_IsLink(t *testing.T) { a := ViewNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestTentativeAccept_IsLink(t *testing.T) { a := TentativeAcceptNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestTentativeReject_IsLink(t *testing.T) { a := TentativeRejectNew("test", Object{}) if a.IsLink() { t.Errorf("%T should respond false to IsLink", a) } } func TestAccept_GetLink(t *testing.T) { a := AcceptNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestAdd_GetLink(t *testing.T) { a := AddNew("test", Object{}, Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestAnnounce_GetLink(t *testing.T) { a := AnnounceNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestArrive_GetLink(t *testing.T) { a := ArriveNew("test") if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestBlock_GetLink(t *testing.T) { a := BlockNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestCreate_GetLink(t *testing.T) { a := CreateNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestDelete_GetLink(t *testing.T) { a := DeleteNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestDislike_GetLink(t *testing.T) { a := DislikeNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestFlag_GetLink(t *testing.T) { a := FlagNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestFollow_GetLink(t *testing.T) { a := FollowNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestIgnore_GetLink(t *testing.T) { a := IgnoreNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestInvite_GetLink(t *testing.T) { a := InviteNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestJoin_GetLink(t *testing.T) { a := JoinNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestLeave_GetLink(t *testing.T) { a := LeaveNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestLike_GetLink(t *testing.T) { a := LikeNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestListen_GetLink(t *testing.T) { a := ListenNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestMove_GetLink(t *testing.T) { a := MoveNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestOffer_GetLink(t *testing.T) { a := OfferNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestQuestion_GetLink(t *testing.T) { a := QuestionNew("test") if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestRead_GetLink(t *testing.T) { a := ReadNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestReject_GetLink(t *testing.T) { a := RejectNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestRemove_GetLink(t *testing.T) { a := RemoveNew("test", Object{}, Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestTravel_GetLink(t *testing.T) { a := TravelNew("test") if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestUndo_GetLink(t *testing.T) { a := UndoNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestUpdate_GetLink(t *testing.T) { a := UpdateNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\"for %T, received %q", a, a.GetLink()) } } func TestView_GetLink(t *testing.T) { a := ViewNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestTentativeAccept_GetLink(t *testing.T) { a := TentativeAcceptNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestTentativeReject_GetLink(t *testing.T) { a := TentativeRejectNew("test", Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetLink()) } } func TestAccept_GetType(t *testing.T) { a := AcceptNew("test", Object{}) if a.GetType() != AcceptType { t.Errorf("GetType should return %q for %T, received %q", AcceptType, a, a.GetType()) } } func TestAdd_GetType(t *testing.T) { a := AddNew("test", Object{}, Object{}) if a.GetType() != AddType { t.Errorf("GetType should return %q for %T, received %q", AddType, a, a.GetType()) } } func TestAnnounce_GetType(t *testing.T) { a := AnnounceNew("test", Object{}) if a.GetType() != AnnounceType { t.Errorf("GetType should return %q for %T, received %q", AnnounceType, a, a.GetType()) } } func TestArrive_GetType(t *testing.T) { a := ArriveNew("test") if a.GetType() != ArriveType { t.Errorf("GetType should return %q for %T, received %q", ArriveType, a, a.GetType()) } } func TestBlock_GetType(t *testing.T) { a := BlockNew("test", Object{}) if a.GetType() != BlockType { t.Errorf("GetType should return %q for %T, received %q", BlockType, a, a.GetType()) } } func TestCreate_GetType(t *testing.T) { a := CreateNew("test", Object{}) if a.GetType() != CreateType { t.Errorf("GetType should return %q for %T, received %q", CreateType, a, a.GetType()) } } func TestDelete_GetType(t *testing.T) { a := DeleteNew("test", Object{}) if a.GetType() != DeleteType { t.Errorf("GetType should return %q for %T, received %q", DeleteType, a, a.GetType()) } } func TestDislike_GetType(t *testing.T) { a := DislikeNew("test", Object{}) if a.GetType() != DislikeType { t.Errorf("GetType should return %q for %T, received %q", DislikeType, a, a.GetType()) } } func TestFlag_GetType(t *testing.T) { a := FlagNew("test", Object{}) if a.GetType() != FlagType { t.Errorf("GetType should return %q for %T, received %q", FlagType, a, a.GetType()) } } func TestFollow_GetType(t *testing.T) { a := FollowNew("test", Object{}) if a.GetType() != FollowType { t.Errorf("GetType should return %q for %T, received %q", FollowType, a, a.GetType()) } } func TestIgnore_GetType(t *testing.T) { a := IgnoreNew("test", Object{}) if a.GetType() != IgnoreType { t.Errorf("GetType should return %q for %T, received %q", IgnoreType, a, a.GetType()) } } func TestInvite_GetType(t *testing.T) { a := InviteNew("test", Object{}) if a.GetType() != InviteType { t.Errorf("GetType should return %q for %T, received %q", InviteType, a, a.GetType()) } } func TestJoin_GetType(t *testing.T) { a := JoinNew("test", Object{}) if a.GetType() != JoinType { t.Errorf("GetType should return %q for %T, received %q", JoinType, a, a.GetType()) } } func TestLeave_GetType(t *testing.T) { a := LeaveNew("test", Object{}) if a.GetType() != LeaveType { t.Errorf("GetType should return %q for %T, received %q", LeaveType, a, a.GetType()) } } func TestLike_GetType(t *testing.T) { a := LikeNew("test", Object{}) if a.GetType() != LikeType { t.Errorf("GetType should return %q for %T, received %q", LikeType, a, a.GetType()) } } func TestListen_GetType(t *testing.T) { a := ListenNew("test", Object{}) if a.GetType() != ListenType { t.Errorf("GetType should return %q for %T, received %q", ListenType, a, a.GetType()) } } func TestMove_GetType(t *testing.T) { a := MoveNew("test", Object{}) if a.GetType() != MoveType { t.Errorf("GetType should return %q for %T, received %q", MoveType, a, a.GetType()) } } func TestOffer_GetType(t *testing.T) { a := OfferNew("test", Object{}) if a.GetType() != OfferType { t.Errorf("GetType should return %q for %T, received %q", OfferType, a, a.GetType()) } } func TestQuestion_GetType(t *testing.T) { a := QuestionNew("test") if a.GetType() != QuestionType { t.Errorf("GetType should return %q for %T, received %q", QuestionType, a, a.GetType()) } } func TestRead_GetType(t *testing.T) { a := ReadNew("test", Object{}) if a.GetType() != ReadType { t.Errorf("GetType should return %q for %T, received %q", ReadType, a, a.GetType()) } } func TestReject_GetType(t *testing.T) { a := RejectNew("test", Object{}) if a.GetType() != RejectType { t.Errorf("GetType should return %q for %T, received %q", RejectType, a, a.GetType()) } } func TestRemove_GetType(t *testing.T) { a := RemoveNew("test", Object{}, Object{}) if a.GetType() != RemoveType { t.Errorf("GetType should return %q for %T, received %q", RemoveType, a, a.GetType()) } } func TestTravel_GetType(t *testing.T) { a := TravelNew("test") if a.GetType() != TravelType { t.Errorf("GetType should return %q for %T, received %q", TravelType, a, a.GetType()) } } func TestUndo_GetType(t *testing.T) { a := UndoNew("test", Object{}) if a.GetType() != UndoType { t.Errorf("GetType should return %q for %T, received %q", UndoType, a, a.GetType()) } } func TestUpdate_GetType(t *testing.T) { a := UpdateNew("test", Object{}) if a.GetType() != UpdateType { t.Errorf("GetType should return %q for %T, received %q", UpdateType, a, a.GetType()) } } func TestView_GetType(t *testing.T) { a := ViewNew("test", Object{}) if a.GetType() != ViewType { t.Errorf("GetType should return %q for %T, received %q", ViewType, a, a.GetType()) } } func TestTentativeAccept_GetType(t *testing.T) { a := TentativeAcceptNew("test", Object{}) if a.GetType() != TentativeAcceptType { t.Errorf("GetType should return %q for %T, received %q", TentativeAcceptType, a, a.GetType()) } } func TestTentativeReject_GetType(t *testing.T) { a := TentativeRejectNew("test", Object{}) if a.GetType() != TentativeRejectType { t.Errorf("GetType should return %q for %T, received %q", TentativeRejectType, a, a.GetType()) } } func TestActivity_GetLink(t *testing.T) { a := ActivityNew("test", ActivityType, Object{}) if a.GetLink() != "test" { t.Errorf("GetLink should return \"test\" for %T, received %q", a, a.GetType()) } } func TestActivity_GetType(t *testing.T) { { a := ActivityNew("test", ActivityType, Object{}) if a.GetType() != ActivityType { t.Errorf("GetType should return %q for %T, received %q", ActivityType, a, a.GetType()) } } { a := ActivityNew("test", AcceptType, Object{}) if a.GetType() != AcceptType { t.Errorf("GetType should return %q for %T, received %q", AcceptType, a, a.GetType()) } } { a := ActivityNew("test", BlockType, Object{}) if a.GetType() != BlockType { t.Errorf("GetType should return %q for %T, received %q", BlockType, a, a.GetType()) } } } func TestIntransitiveActivity_GetType(t *testing.T) { { a := IntransitiveActivityNew("test", IntransitiveActivityType) if a.GetType() != IntransitiveActivityType { t.Errorf("GetType should return %q for %T, received %q", IntransitiveActivityType, a, a.GetType()) } } { a := IntransitiveActivityNew("test", ArriveType) if a.GetType() != ArriveType { t.Errorf("GetType should return %q for %T, received %q", ArriveType, a, a.GetType()) } } { a := IntransitiveActivityNew("test", QuestionType) if a.GetType() != QuestionType { t.Errorf("GetType should return %q for %T, received %q", QuestionType, a, a.GetType()) } } } func TestActivity_UnmarshalJSON(t *testing.T) { a := Activity{} dataEmpty := []byte("{}") a.UnmarshalJSON(dataEmpty) if a.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", a, a.ID) } if a.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", a, a.Type) } if a.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", a, a.AttributedTo) } if len(a.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", a, a.Name) } if len(a.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", a, a.Summary) } if len(a.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", a, a.Content) } if a.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", a, a.URL) } if !a.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", a, a.Published) } if !a.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", a, a.StartTime) } if !a.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", a, a.Updated) } } func TestCreate_UnmarshalJSON(t *testing.T) { c := Create{} dataEmpty := []byte("{}") c.UnmarshalJSON(dataEmpty) if c.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", c, c.ID) } if c.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", c, c.Type) } if c.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", c, c.AttributedTo) } if len(c.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", c, c.Name) } if len(c.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", c, c.Summary) } if len(c.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", c, c.Content) } if c.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", c, c.URL) } if !c.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", c, c.Published) } if !c.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", c, c.StartTime) } if !c.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", c, c.Updated) } } func TestDislike_UnmarshalJSON(t *testing.T) { d := Dislike{} dataEmpty := []byte("{}") d.UnmarshalJSON(dataEmpty) if d.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", d, d.ID) } if d.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", d, d.Type) } if d.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", d, d.AttributedTo) } if len(d.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", d, d.Name) } if len(d.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", d, d.Summary) } if len(d.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", d, d.Content) } if d.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", d, d.URL) } if !d.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", d, d.Published) } if !d.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", d, d.StartTime) } if !d.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", d, d.Updated) } } func TestLike_UnmarshalJSON(t *testing.T) { l := Like{} dataEmpty := []byte("{}") l.UnmarshalJSON(dataEmpty) if l.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", l, l.ID) } if l.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", l, l.Type) } if l.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", l, l.AttributedTo) } if len(l.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", l, l.Name) } if len(l.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", l, l.Summary) } if len(l.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", l, l.Content) } if l.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", l, l.URL) } if !l.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", l, l.Published) } if !l.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", l, l.StartTime) } if !l.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", l, l.Updated) } } func TestUpdate_UnmarshalJSON(t *testing.T) { u := Update{} dataEmpty := []byte("{}") u.UnmarshalJSON(dataEmpty) if u.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", u, u.ID) } if u.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", u, u.Type) } if u.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", u, u.AttributedTo) } if len(u.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", u, u.Name) } if len(u.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", u, u.Summary) } if len(u.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", u, u.Content) } if u.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", u, u.URL) } if !u.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", u, u.Published) } if !u.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", u, u.StartTime) } if !u.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", u, u.Updated) } }
-
-
activitystreams/actors.go (deleted)
-
@@ -1,433 +0,0 @@package activitystreams // Actor Types const ( ApplicationType ActivityVocabularyType = "Application" GroupType ActivityVocabularyType = "Group" OrganizationType ActivityVocabularyType = "Organization" PersonType ActivityVocabularyType = "Person" ServiceType ActivityVocabularyType = "Service" ) var validActorTypes = [...]ActivityVocabularyType{ ApplicationType, GroupType, OrganizationType, PersonType, ServiceType, } // Endpoints a json object which maps additional (typically server/domain-wide) // endpoints which may be useful either for this actor or someone referencing this actor. // This mapping may be nested inside the actor document as the value or may be a link to // a JSON-LD document with these properties. type Endpoints struct { // UploadMedia Upload endpoint URI for this user for binary data. UploadMedia Item `jsonld:"uploadMedia,omitempty"` // OauthAuthorizationEndpoint Endpoint URI so this actor's clients may access remote ActivityStreams objects which require authentication // to access. To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value being // the id of the requested ActivityStreams object. OauthAuthorizationEndpoint Item `jsonld:"oauthAuthorizationEndpoint,omitempty"` // OauthTokenEndpoint If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, // this endpoint specifies a URI at which a browser-authenticated user may obtain a new authorization grant. OauthTokenEndpoint Item `jsonld:"oauthTokenEndpoint,omitempty"` // ProvideClientKey If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, // this endpoint specifies a URI at which a client may acquire an access token. ProvideClientKey Item `jsonld:"provideClientKey,omitempty"` // SignClientKey If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, // this endpoint specifies a URI at which browser-authenticated users may authorize a client's public // key for client to server interactions. SignClientKey Item `jsonld:"signClientKey,omitempty"` // SharedInbox If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, // this endpoint specifies a URI at which a client key may be signed by the actor's key for a time window to // act on behalf of the actor in interacting with foreign servers. SharedInbox Item `jsonld:"sharedInbox,omitempty"` } type WillAct interface { Item GetActor() Actor } // Actor is generally one of the ActivityStreams Actor Types, but they don't have to be. // For example, a Profile object might be used as an actor, or a type from an ActivityStreams extension. // Actors are retrieved like any other Object in ActivityPub. // Like other ActivityStreams objects, actors have an id, which is a URI. type Actor struct { Parent // A reference to an [ActivityStreams] OrderedCollection comprised of all the messages received by the actor; // see 5.2 Inbox. Inbox Item `jsonld:"inbox,omitempty"` // An [ActivityStreams] OrderedCollection comprised of all the messages produced by the actor; // see 5.1 Outbox. Outbox Item `jsonld:"outbox,omitempty"` // A link to an [ActivityStreams] collection of the actors that this actor is following; // see 5.4 Following Collection Following Item `jsonld:"following,omitempty"` // A link to an [ActivityStreams] collection of the actors that follow this actor; // see 5.3 Followers Collection. Followers Item `jsonld:"followers,omitempty"` // A link to an [ActivityStreams] collection of the actors that follow this actor; // see 5.3 Followers Collection. Liked Item `jsonld:"liked,omitempty"` // A short username which may be used to refer to the actor, with no uniqueness guarantees. PreferredUsername NaturalLanguageValue `jsonld:"preferredUsername,omitempty,collapsible"` // A json object which maps additional (typically server/domain-wide) endpoints which may be useful either // for this actor or someone referencing this actor. // This mapping may be nested inside the actor document as the value or may be a link // to a JSON-LD document with these properties. Endpoints Endpoints `jsonld:"endpoints,omitempty"` // A list of supplementary Collections which may be of interest. Streams []Item `jsonld:"streams,omitempty"` } // ActorInterface type ActorInterface interface{} type ( // Application describes a software application. Application Actor // Group represents a formal or informal collective of Actors. Group Actor // Organization represents an organization. Organization Actor // Person represents an individual person. Person Actor // Service represents a service of any kind. Service Actor ) // ValidActorType validates the passed type against the valid actor types func ValidActorType(typ ActivityVocabularyType) bool { for _, v := range validActorTypes { if v == typ { return true } } return false } // ActorNew initializes an Actor type actor func ActorNew(id ObjectID, typ ActivityVocabularyType) *Actor { if !ValidActorType(typ) { typ = ActorType } a := Actor{Parent: Parent{ID: id, Type: typ}} a.Name = NaturalLanguageValueNew() a.Content = NaturalLanguageValueNew() a.Summary = NaturalLanguageValueNew() in := OrderedCollectionNew(ObjectID("test-inbox")) out := OrderedCollectionNew(ObjectID("test-outbox")) liked := OrderedCollectionNew(ObjectID("test-liked")) a.Inbox = in a.Outbox = out a.Liked = liked a.PreferredUsername = NaturalLanguageValueNew() return &a } // ApplicationNew initializes an Application type actor func ApplicationNew(id ObjectID) *Application { a := ActorNew(id, ApplicationType) o := Application(*a) return &o } // GroupNew initializes a Group type actor func GroupNew(id ObjectID) *Group { a := ActorNew(id, GroupType) o := Group(*a) return &o } // OrganizationNew initializes an Organization type actor func OrganizationNew(id ObjectID) *Organization { a := ActorNew(id, OrganizationType) o := Organization(*a) return &o } // PersonNew initializes a Person type actor func PersonNew(id ObjectID) *Person { a := ActorNew(id, PersonType) o := Person(*a) return &o } // ServiceNew initializes a Service type actor func ServiceNew(id ObjectID) *Service { a := ActorNew(id, ServiceType) o := Service(*a) return &o } // IsLink validates if current Actor is a Link func (a Actor) IsLink() bool { return a.Type == LinkType || ValidLinkType(a.Type) } // IsObject validates if current Actor is an Object func (a Actor) IsObject() bool { return a.Type == ObjectType || ValidObjectType(a.Type) } // GetID returns the ObjectID corresponding to the Actor object func (a Actor) GetID() *ObjectID { return &a.ID } // GetLink returns the IRI corresponding to the Actor object func (a Actor) GetLink() IRI { return IRI(a.ID) } // GetType returns the type corresponding to the Actor object func (a Actor) GetType() ActivityVocabularyType { return a.Type } // IsLink validates if current Application is a Link func (a Application) IsLink() bool { return a.Type == LinkType || ValidLinkType(a.Type) } // IsObject validates if current Application is an Object func (a Application) IsObject() bool { return a.Type == ObjectType || ValidObjectType(a.Type) } // GetID returns the ObjectID corresponding to the Application object func (a Application) GetID() *ObjectID { return a.GetActor().GetID() } // GetLink returns the IRI corresponding to the Application object func (a Application) GetLink() IRI { return IRI(a.ID) } // GetType returns the type corresponding to the Application object func (a Application) GetType() ActivityVocabularyType { return a.Type } // IsLink validates if current Group is a Link func (g Group) IsLink() bool { return g.Type == LinkType || ValidLinkType(g.Type) } // IsObject validates if current Group is an Object func (g Group) IsObject() bool { return g.Type == ObjectType || ValidObjectType(g.Type) } // GetID returns the ObjectID corresponding to the Group object func (g Group) GetID() *ObjectID { return g.GetActor().GetID() } // GetLink returns the IRI corresponding to the Group object func (g Group) GetLink() IRI { return IRI(g.ID) } // GetType returns the type corresponding to the Group object func (g Group) GetType() ActivityVocabularyType { return g.Type } // IsLink validates if current Organization is a Link func (o Organization) IsLink() bool { return o.Type == LinkType || ValidLinkType(o.Type) } // IsObject validates if current Organization is an Object func (o Organization) IsObject() bool { return o.Type == ObjectType || ValidObjectType(o.Type) } // GetID returns the ObjectID corresponding to the Organization object func (o Organization) GetID() *ObjectID { return o.GetActor().GetID() } // GetLink returns the IRI corresponding to the Organization object func (o Organization) GetLink() IRI { return IRI(o.ID) } // GetType returns the type corresponding to the Organization object func (o Organization) GetType() ActivityVocabularyType { return o.Type } // IsLink validates if current Service is a Link func (s Service) IsLink() bool { return s.Type == LinkType || ValidLinkType(s.Type) } // IsObject validates if current Service is an Object func (s Service) IsObject() bool { return s.Type == ObjectType || ValidObjectType(s.Type) } // GetID returns the ObjectID corresponding to the Service object func (s Service) GetID() *ObjectID { return s.GetActor().GetID() } // GetLink returns the IRI corresponding to the Service object func (s Service) GetLink() IRI { return IRI(s.ID) } // GetType returns the type corresponding to the Service object func (s Service) GetType() ActivityVocabularyType { return s.Type } // IsLink validates if current Person is a Link func (p Person) IsLink() bool { return p.Type == LinkType || ValidLinkType(p.Type) } // IsObject validates if current Person is an Object func (p Person) IsObject() bool { return p.Type == ObjectType || ValidObjectType(p.Type) } // GetID returns the ObjectID corresponding to the Person object func (p Person) GetID() *ObjectID { return p.GetActor().GetID() } // GetType returns the object type for the current Person object func (p Person) GetType() ActivityVocabularyType { return p.Type } // GetLink returns the IRI corresponding to the Person object func (p Person) GetLink() IRI { return IRI(p.ID) } // UnmarshalJSON func (a *Actor) UnmarshalJSON(data []byte) error { a.Parent.UnmarshalJSON(data) a.PreferredUsername = getAPNaturalLanguageField(data, "preferredUsername") out := getAPItem(data, "outbox") if out != nil { a.Outbox = out } inb := getAPItem(data, "inbox") if inb != nil { a.Inbox = inb } followers := getAPItem(data, "followers") if followers != nil { a.Followers = followers } following := getAPItem(data, "following") if following != nil { a.Following = following } liked := getAPItem(data, "liked") if liked != nil { a.Liked = liked } streams := getAPItems(data, "streams") if streams != nil { a.Streams = streams } // @todo(marius) : Add getAPIEndPoints return nil } func (p *Person) UnmarshalJSON(data []byte) error { a := p.GetActor() err := a.UnmarshalJSON(data) *p = Person(a) return err } // UnmarshalJSON func (a *Application) UnmarshalJSON(data []byte) error { act := a.GetActor() err := act.UnmarshalJSON(data) *a = Application(act) return err } // UnmarshalJSON func (g *Group) UnmarshalJSON(data []byte) error { a := g.GetActor() err := a.UnmarshalJSON(data) *g = Group(a) return err } // UnmarshalJSON func (o *Organization) UnmarshalJSON(data []byte) error { a := o.GetActor() err := a.UnmarshalJSON(data) *o = Organization(a) return err } // UnmarshalJSON func (s *Service) UnmarshalJSON(data []byte) error { a := s.GetActor() err := a.UnmarshalJSON(data) *s = Service(a) return err } // GetActor returns the underlying Actor type func (a Actor) GetActor() Actor { return a } // GetActor returns the underlying Actor type func (a Application) GetActor() Actor { return Actor(a) } // GetActor returns the underlying Actor type func (g Group) GetActor() Actor { return Actor(g) } // GetActor returns the underlying Actor type func (o Organization) GetActor() Actor { return Actor(o) } // GetActor returns the underlying Actor type func (p Person) GetActor() Actor { return Actor(p) } // GetActor returns the underlying Actor type func (s Service) GetActor() Actor { return Actor(s) }
-
-
activitystreams/actors_test.go (deleted)
-
@@ -1,346 +0,0 @@package activitystreams import ( "reflect" "testing" ) func TestActorNew(t *testing.T) { var testValue = ObjectID("test") var testType = ApplicationType o := ActorNew(testValue, testType) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != testType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, testType) } n := ActorNew(testValue, "") if n.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", n.ID, testValue) } if n.Type != ActorType { t.Errorf("APObject Type '%v' different than expected '%v'", n.Type, ActorType) } } func TestPersonNew(t *testing.T) { var testValue = ObjectID("test") o := PersonNew(testValue) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != PersonType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, PersonType) } } func TestApplicationNew(t *testing.T) { var testValue = ObjectID("test") o := ApplicationNew(testValue) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != ApplicationType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, ApplicationType) } } func TestGroupNew(t *testing.T) { var testValue = ObjectID("test") o := GroupNew(testValue) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != GroupType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, GroupType) } } func TestOrganizationNew(t *testing.T) { var testValue = ObjectID("test") o := OrganizationNew(testValue) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != OrganizationType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, OrganizationType) } } func TestServiceNew(t *testing.T) { var testValue = ObjectID("test") o := ServiceNew(testValue) if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != ServiceType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, ServiceType) } } func TestValidActorType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidActorType(invalidType) { t.Errorf("APObject Type '%v' should not be valid", invalidType) } for _, validType := range validActorTypes { if !ValidActorType(validType) { t.Errorf("APObject Type '%v' should be valid", validType) } } } func TestActor_IsLink(t *testing.T) { m := ActorNew("test", ActorType) if m.IsLink() { t.Errorf("%#v should not be a valid Link", m.Type) } } func TestActor_IsObject(t *testing.T) { m := ActorNew("test", ActorType) if !m.IsObject() { t.Errorf("%#v should be a valid object", m.Type) } } func TestActor_Object(t *testing.T) { m := ActorNew("test", ActorType) if reflect.DeepEqual(ObjectID(""), m.GetID()) { t.Errorf("%#v should not be an empty activity pub object", m.GetID()) } } func TestActor_Type(t *testing.T) { m := ActorNew("test", ActorType) if m.GetType() != ActorType { t.Errorf("%#v should be an empty Link object", m.GetType()) } } func TestPerson_IsLink(t *testing.T) { m := PersonNew("test") if m.IsLink() { t.Errorf("%T should not be a valid Link", m) } } func TestPerson_IsObject(t *testing.T) { m := PersonNew("test") if !m.IsObject() { t.Errorf("%T should be a valid object", m) } } func TestActor_UnmarshalJSON(t *testing.T) { } func TestActor_GetActor(t *testing.T) { } func TestActor_GetID(t *testing.T) { } func TestActor_GetLink(t *testing.T) { } func TestActor_GetType(t *testing.T) { } func TestApplication_GetActor(t *testing.T) { } func TestApplication_GetID(t *testing.T) { } func TestApplication_GetLink(t *testing.T) { } func TestApplication_GetType(t *testing.T) { } func TestApplication_IsLink(t *testing.T) { } func TestApplication_IsObject(t *testing.T) { } func TestGroup_GetActor(t *testing.T) { } func TestGroup_GetID(t *testing.T) { } func TestGroup_GetLink(t *testing.T) { } func TestGroup_GetType(t *testing.T) { } func TestGroup_IsLink(t *testing.T) { } func TestGroup_IsObject(t *testing.T) { } func TestOrganization_GetActor(t *testing.T) { } func TestOrganization_GetID(t *testing.T) { } func TestOrganization_GetLink(t *testing.T) { } func TestOrganization_GetType(t *testing.T) { } func TestOrganization_IsLink(t *testing.T) { } func TestOrganization_IsObject(t *testing.T) { } func TestPerson_GetActor(t *testing.T) { } func TestPerson_GetID(t *testing.T) { } func TestPerson_GetLink(t *testing.T) { } func TestPerson_GetType(t *testing.T) { } func validateEmptyPerson(p Person, t *testing.T) { if p.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", p, p.ID) } if p.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", p, p.Type) } if p.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", p, p.AttributedTo) } if len(p.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", p, p.Name) } if len(p.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", p, p.Summary) } if len(p.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", p, p.Content) } if p.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", p, p.URL) } if !p.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", p, p.Published) } if !p.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", p, p.StartTime) } if !p.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", p, p.Updated) } } func TestPerson_UnmarshalJSON(t *testing.T) { p := Person{} dataEmpty := []byte("{}") p.UnmarshalJSON(dataEmpty) validateEmptyPerson(p, t) } func TestApplication_UnmarshalJSON(t *testing.T) { a := Application{} dataEmpty := []byte("{}") a.UnmarshalJSON(dataEmpty) validateEmptyPerson(Person(a), t) } func TestGroup_UnmarshalJSON(t *testing.T) { g := Group{} dataEmpty := []byte("{}") g.UnmarshalJSON(dataEmpty) validateEmptyPerson(Person(g), t) } func TestOrganization_UnmarshalJSON(t *testing.T) { o := Organization{} dataEmpty := []byte("{}") o.UnmarshalJSON(dataEmpty) validateEmptyPerson(Person(o), t) } func TestService_UnmarshalJSON(t *testing.T) { s := Service{} dataEmpty := []byte("{}") s.UnmarshalJSON(dataEmpty) validateEmptyPerson(Person(s), t) } func TestService_GetActor(t *testing.T) { } func TestService_GetID(t *testing.T) { } func TestService_GetLink(t *testing.T) { } func TestService_GetType(t *testing.T) { } func TestService_IsLink(t *testing.T) { } func TestService_IsObject(t *testing.T) { }
-
-
activitystreams/collections.go (deleted)
-
@@ -1,283 +0,0 @@package activitystreams import ( "github.com/buger/jsonparser" ) var validCollectionTypes = [...]ActivityVocabularyType{ CollectionType, OrderedCollectionType, CollectionPageType, OrderedCollectionPageType, } type CollectionInterface interface { ObjectOrLink Collection() CollectionInterface Append(ob Item) error } // Collection is a subtype of Activity Pub Object that represents ordered or unordered sets of Activity Pub Object or Link instances. type Collection struct { Parent // In a paged Collection, indicates the page that contains the most recently updated member items. Current ObjectOrLink `jsonld:"current,omitempty"` // In a paged Collection, indicates the furthest preceeding page of items in the collection. First ObjectOrLink `jsonld:"first,omitempty"` // In a paged Collection, indicates the furthest proceeding page of the collection. Last ObjectOrLink `jsonld:"last,omitempty"` // A non-negative integer specifying the total number of objects contained by the logical view of the collection. // This number might not reflect the actual number of items serialized within the Collection object instance. TotalItems uint `jsonld:"totalItems,omitempty"` // Identifies the items contained in a collection. The items might be ordered or unordered. Items ItemCollection `jsonld:"items,omitempty"` } // OrderedCollection is a subtype of Collection in which members of the logical // collection are assumed to always be strictly ordered. type OrderedCollection struct { Parent // In a paged Collection, indicates the page that contains the most recently updated member items. Current ObjectOrLink `jsonld:"current,omitempty"` // In a paged Collection, indicates the furthest preceeding page of items in the collection. First ObjectOrLink `jsonld:"first,omitempty"` // In a paged Collection, indicates the furthest proceeding page of the collection. Last ObjectOrLink `jsonld:"last,omitempty"` // A non-negative integer specifying the total number of objects contained by the logical view of the collection. // This number might not reflect the actual number of items serialized within the Collection object instance. TotalItems uint `jsonld:"totalItems,omitempty"` // Identifies the items contained in a collection. The items might be ordered or unordered. OrderedItems ItemCollection `jsonld:"orderedItems,omitempty"` } // CollectionPage is a Collection that contains a large number of items and when it becomes impractical // for an implementation to serialize every item contained by a Collection using the items (or orderedItems) // property alone. In such cases, the items within a Collection can be divided into distinct subsets or "pages". type CollectionPage struct { Collection // Identifies the Collection to which a CollectionPage objects items belong. PartOf Item `jsonld:"partOf,omitempty"` // In a paged Collection, indicates the next page of items. Next Item `jsonld:"next,omitempty"` // In a paged Collection, identifies the previous page of items. Prev Item `jsonld:"prev,omitempty"` } // OrderedCollectionPage type extends from both CollectionPage and OrderedCollection. // In addition to the properties inherited from each of those, the OrderedCollectionPage // may contain an additional startIndex property whose value indicates the relative index position // of the first item contained by the page within the OrderedCollection to which the page belongs. type OrderedCollectionPage struct { OrderedCollection // Identifies the Collection to which a CollectionPage objects items belong. PartOf Item `jsonld:"partOf,omitempty"` // In a paged Collection, indicates the next page of items. Next Item `jsonld:"next,omitempty"` // In a paged Collection, identifies the previous page of items. Prev Item `jsonld:"prev,omitempty"` // A non-negative integer value identifying the relative position within the logical view of a strictly ordered collection. StartIndex uint `jsonld:"startIndex,omitempty"` } // ValidCollectionType validates against the valid collection types func ValidCollectionType(typ ActivityVocabularyType) bool { for _, v := range validCollectionTypes { if v == typ { return true } } return false } // CollectionNew initializes a new Collection func CollectionNew(id ObjectID) *Collection { c := Collection{Parent: Parent{ID: id, Type: CollectionType}} c.Name = NaturalLanguageValueNew() c.Content = NaturalLanguageValueNew() c.Summary = NaturalLanguageValueNew() return &c } // OrderedCollectionNew initializes a new OrderedCollection func OrderedCollectionNew(id ObjectID) *OrderedCollection { o := OrderedCollection{Parent: Parent{ID: id, Type: OrderedCollectionType}} o.Name = NaturalLanguageValueNew() o.Content = NaturalLanguageValueNew() return &o } // CollectionNew initializes a new CollectionPage func CollectionPageNew(parent CollectionInterface) *CollectionPage { p := CollectionPage{ PartOf: parent.GetLink(), } if pc, ok := parent.(*Collection); ok { p.Collection = *pc } p.Type = CollectionPageType return &p } // OrderedCollectionPageNew initializes a new OrderedCollectionPage func OrderedCollectionPageNew(parent CollectionInterface) *OrderedCollectionPage { p := OrderedCollectionPage{ PartOf: parent.GetLink(), } if pc, ok := parent.(*OrderedCollection); ok { p.OrderedCollection = *pc } p.Type = OrderedCollectionPageType return &p } // Append adds an element to an OrderedCollection func (o *OrderedCollection) Append(ob Item) error { o.OrderedItems = append(o.OrderedItems, ob) o.TotalItems++ return nil } // Append adds an element to a Collection func (c *Collection) Append(ob Item) error { c.Items = append(c.Items, ob) c.TotalItems++ return nil } // Append adds an element to an OrderedCollectionPage func (o *OrderedCollectionPage) Append(ob Item) error { o.OrderedItems = append(o.OrderedItems, ob) o.TotalItems++ return nil } // Append adds an element to a CollectionPage func (c *CollectionPage) Append(ob Item) error { c.Items = append(c.Items, ob) c.TotalItems++ return nil } // GetType returns the Collection's type func (c Collection) GetType() ActivityVocabularyType { return c.Type } // IsLink returns false for a Collection object func (c Collection) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the Collection object func (c Collection) GetID() *ObjectID { return &c.ID } // GetLink returns the IRI corresponding to the Collection object func (c Collection) GetLink() IRI { return IRI(c.ID) } // IsObject returns true for a Collection object func (c Collection) IsObject() bool { return true } // GetType returns the OrderedCollection's type func (o OrderedCollection) GetType() ActivityVocabularyType { return o.Type } // IsLink returns false for an OrderedCollection object func (o OrderedCollection) IsLink() bool { return false } // GetID returns the ObjectID corresponding to the OrderedCollection func (o OrderedCollection) GetID() *ObjectID { return &o.ID } // GetLink returns the IRI corresponding to the OrderedCollection object func (o OrderedCollection) GetLink() IRI { return IRI(o.ID) } // IsObject returns true for am OrderedCollection object func (o OrderedCollection) IsObject() bool { return true } // UnmarshalJSON func (o *OrderedCollection) UnmarshalJSON(data []byte) error { o.Parent.UnmarshalJSON(data) o.TotalItems = uint(getAPInt(data, "totalItems")) o.OrderedItems = getAPItems(data, "orderedItems") o.Current = getAPItem(data, "current") o.First = getAPItem(data, "first") o.Last = getAPItem(data, "last") return nil } // UnmarshalJSON func (c *Collection) UnmarshalJSON(data []byte) error { c.Parent.UnmarshalJSON(data) c.TotalItems = uint(getAPInt(data, "totalItems")) c.Items = getAPItems(data, "items") c.Current = getAPItem(data, "current") c.First = getAPItem(data, "first") c.Last = getAPItem(data, "last") return nil } // UnmarshalJSON func (o *OrderedCollectionPage) UnmarshalJSON(data []byte) error { o.OrderedCollection.UnmarshalJSON(data) o.Next = getAPItem(data, "next") o.Prev = getAPItem(data, "prev") o.PartOf = getAPItem(data, "partOf") if si, err := jsonparser.GetInt(data, "startIndex"); err != nil { o.StartIndex = uint(si) } return nil } // UnmarshalJSON func (c *CollectionPage) UnmarshalJSON(data []byte) error { c.Collection.UnmarshalJSON(data) c.Next = getAPItem(data, "next") c.Prev = getAPItem(data, "prev") c.PartOf = getAPItem(data, "partOf") return nil } /* func (c *Collection) MarshalJSON() ([]byte, error) { return nil, nil } func (o *OrderedCollection) MarshalJSON() ([]byte, error) { return nil, nil } */ // Collection returns the underlying Collection type func (c *Collection) Collection() CollectionInterface { return c } // Collection returns the underlying Collection type func (o *OrderedCollection) Collection() CollectionInterface { return o }
-
-
activitystreams/collections_test.go (deleted)
-
@@ -1,491 +0,0 @@package activitystreams import ( "reflect" "testing" ) func TestCollectionNew(t *testing.T) { var testValue = ObjectID("test") c := CollectionNew(testValue) if c.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", c.ID, testValue) } if c.Type != CollectionType { t.Errorf("APObject Type '%v' different than expected '%v'", c.Type, CollectionType) } } func TestOrderedCollectionNew(t *testing.T) { var testValue = ObjectID("test") c := OrderedCollectionNew(testValue) if c.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", c.ID, testValue) } if c.Type != OrderedCollectionType { t.Errorf("APObject Type '%v' different than expected '%v'", c.Type, OrderedCollectionType) } } func TestCollectionPageNew(t *testing.T) { var testValue = ObjectID("test") c := CollectionNew(testValue) p := CollectionPageNew(c) if reflect.DeepEqual(p.Collection, c) { t.Errorf("Invalid collection parent '%v'", p.PartOf) } if p.PartOf != c.GetLink() { t.Errorf("Invalid collection '%v'", p.PartOf) } } func TestOrderedCollectionPageNew(t *testing.T) { var testValue = ObjectID("test") c := OrderedCollectionNew(testValue) p := OrderedCollectionPageNew(c) if reflect.DeepEqual(p.OrderedCollection, c) { t.Errorf("Invalid ordered collection parent '%v'", p.PartOf) } if p.PartOf != c.GetLink() { t.Errorf("Invalid collection '%v'", p.PartOf) } } func TestValidCollectionType(t *testing.T) { for _, validType := range validCollectionTypes { if !ValidCollectionType(validType) { t.Errorf("Generic Type '%#v' should be valid", validType) } } } func Test_OrderedCollection_Append(t *testing.T) { id := ObjectID("test") val := Object{ID: ObjectID("grrr")} c := OrderedCollectionNew(id) c.Append(val) if c.TotalItems != 1 { t.Errorf("Inbox collection of %q should have one element", *c.GetID()) } if !reflect.DeepEqual(c.OrderedItems[0], val) { t.Errorf("First item in Inbox is does not match %q", val.ID) } } func TestCollection_Append(t *testing.T) { id := ObjectID("test") val := Object{ID: ObjectID("grrr")} c := CollectionNew(id) c.Append(val) if c.TotalItems != 1 { t.Errorf("Inbox collection of %q should have one element", *c.GetID()) } if !reflect.DeepEqual(c.Items[0], val) { t.Errorf("First item in Inbox is does not match %q", val.ID) } } func TestCollectionPage_Append(t *testing.T) { id := ObjectID("test") val := Object{ID: ObjectID("grrr")} c := CollectionNew(id) p := CollectionPageNew(c) p.Append(val) if p.PartOf != c.GetLink() { t.Errorf("Collection page should point to collection %q", c.GetLink()) } if p.TotalItems != 1 { t.Errorf("Collection page of %q should have exactly one element", *p.GetID()) } if !reflect.DeepEqual(p.Items[0], val) { t.Errorf("First item in Inbox is does not match %q", val.ID) } } func TestCollection_Collection(t *testing.T) { id := ObjectID("test") c := CollectionNew(id) if c.Collection() != c { t.Errorf("Collection should return itself %q", *c.GetID()) } } func TestCollection_GetID(t *testing.T) { id := ObjectID("test") c := CollectionNew(id) if *c.GetID() != id { t.Errorf("GetID should return %s, received %s", id, *c.GetID()) } } func TestCollection_GetLink(t *testing.T) { id := ObjectID("test") link := IRI(id) c := CollectionNew(id) if c.GetLink() != link { t.Errorf("GetLink should return %q, received %q", link, c.GetLink()) } } func TestCollection_GetType(t *testing.T) { id := ObjectID("test") c := CollectionNew(id) if c.GetType() != CollectionType { t.Errorf("Collection Type should be %q, received %q", CollectionType, c.GetType()) } } func TestCollection_IsLink(t *testing.T) { id := ObjectID("test") c := CollectionNew(id) if c.IsLink() != false { t.Errorf("Collection should not be a link, received %t", c.IsLink()) } } func TestCollection_IsObject(t *testing.T) { id := ObjectID("test") c := CollectionNew(id) if c.IsObject() != true { t.Errorf("Collection should be an object, received %t", c.IsObject()) } } func TestCollection_UnmarshalJSON(t *testing.T) { c := Collection{} dataEmpty := []byte("{}") c.UnmarshalJSON(dataEmpty) if c.ID != "" { t.Errorf("Unmarshalled object should have empty ID, received %q", c.ID) } if c.Type != "" { t.Errorf("Unmarshalled object should have empty Type, received %q", c.Type) } if c.AttributedTo != nil { t.Errorf("Unmarshalled object should have empty AttributedTo, received %q", c.AttributedTo) } if len(c.Name) != 0 { t.Errorf("Unmarshalled object should have empty Name, received %q", c.Name) } if len(c.Summary) != 0 { t.Errorf("Unmarshalled object should have empty Summary, received %q", c.Summary) } if len(c.Content) != 0 { t.Errorf("Unmarshalled object should have empty Content, received %q", c.Content) } if c.TotalItems != 0 { t.Errorf("Unmarshalled object should have empty TotalItems, received %d", c.TotalItems) } if len(c.Items) > 0 { t.Errorf("Unmarshalled object should have empty Items, received %v", c.Items) } if c.URL != nil { t.Errorf("Unmarshalled object should have empty URL, received %v", c.URL) } if !c.Published.IsZero() { t.Errorf("Unmarshalled object should have empty Published, received %q", c.Published) } if !c.StartTime.IsZero() { t.Errorf("Unmarshalled object should have empty StartTime, received %q", c.StartTime) } if !c.Updated.IsZero() { t.Errorf("Unmarshalled object should have empty Updated, received %q", c.Updated) } } func TestCollectionPage_UnmarshalJSON(t *testing.T) { p := CollectionPage{} dataEmpty := []byte("{}") p.UnmarshalJSON(dataEmpty) if p.ID != "" { t.Errorf("Unmarshalled object should have empty ID, received %q", p.ID) } if p.Type != "" { t.Errorf("Unmarshalled object should have empty Type, received %q", p.Type) } if p.AttributedTo != nil { t.Errorf("Unmarshalled object should have empty AttributedTo, received %q", p.AttributedTo) } if len(p.Name) != 0 { t.Errorf("Unmarshalled object should have empty Name, received %q", p.Name) } if len(p.Summary) != 0 { t.Errorf("Unmarshalled object should have empty Summary, received %q", p.Summary) } if len(p.Content) != 0 { t.Errorf("Unmarshalled object should have empty Content, received %q", p.Content) } if p.TotalItems != 0 { t.Errorf("Unmarshalled object should have empty TotalItems, received %d", p.TotalItems) } if len(p.Items) > 0 { t.Errorf("Unmarshalled object should have empty Items, received %v", p.Items) } if p.URL != nil { t.Errorf("Unmarshalled object should have empty URL, received %v", p.URL) } if !p.Published.IsZero() { t.Errorf("Unmarshalled object should have empty Published, received %q", p.Published) } if !p.StartTime.IsZero() { t.Errorf("Unmarshalled object should have empty StartTime, received %q", p.StartTime) } if !p.Updated.IsZero() { t.Errorf("Unmarshalled object should have empty Updated, received %q", p.Updated) } if p.PartOf != nil { t.Errorf("Unmarshalled object should have empty PartOf, received %q", p.PartOf) } if p.Current != nil { t.Errorf("Unmarshalled object should have empty Current, received %q", p.Current) } if p.First != nil { t.Errorf("Unmarshalled object should have empty First, received %q", p.First) } if p.Last != nil { t.Errorf("Unmarshalled object should have empty Last, received %q", p.Last) } if p.Next != nil { t.Errorf("Unmarshalled object should have empty Next, received %q", p.Next) } if p.Prev != nil { t.Errorf("Unmarshalled object should have empty Prev, received %q", p.Prev) } } func TestOrderedCollection_Append(t *testing.T) { id := ObjectID("test") val := Object{ID: ObjectID("grrr")} c := OrderedCollectionNew(id) p := OrderedCollectionPageNew(c) p.Append(val) if p.PartOf != c.GetLink() { t.Errorf("Ordereed collection page should point to ordered collection %q", c.GetLink()) } if p.TotalItems != 1 { t.Errorf("Ordered collection page of %q should have exactly one element", *p.GetID()) } if !reflect.DeepEqual(p.OrderedItems[0], val) { t.Errorf("First item in Inbox is does not match %q", val.ID) } } func TestOrderedCollection_Collection(t *testing.T) { id := ObjectID("test") c := OrderedCollectionNew(id) if c.Collection() != c { t.Errorf("Collection should return itself %q", *c.GetID()) } } func TestOrderedCollection_GetID(t *testing.T) { id := ObjectID("test") c := OrderedCollectionNew(id) if *c.GetID() != id { t.Errorf("GetID should return %q, received %q", id, *c.GetID()) } } func TestOrderedCollection_GetLink(t *testing.T) { id := ObjectID("test") link := IRI(id) c := OrderedCollectionNew(id) if c.GetLink() != link { t.Errorf("GetLink should return %q, received %q", link, c.GetLink()) } } func TestOrderedCollection_GetType(t *testing.T) { id := ObjectID("test") c := OrderedCollectionNew(id) if c.GetType() != OrderedCollectionType { t.Errorf("OrderedCollection Type should be %q, received %q", OrderedCollectionType, c.GetType()) } } func TestOrderedCollection_IsLink(t *testing.T) { id := ObjectID("test") c := OrderedCollectionNew(id) if c.IsLink() != false { t.Errorf("OrderedCollection should not be a link, received %t", c.IsLink()) } } func TestOrderedCollection_IsObject(t *testing.T) { id := ObjectID("test") c := OrderedCollectionNew(id) if c.IsObject() != true { t.Errorf("OrderedCollection should be an object, received %t", c.IsObject()) } } func TestOrderedCollection_UnmarshalJSON(t *testing.T) { c := OrderedCollection{} dataEmpty := []byte("{}") c.UnmarshalJSON(dataEmpty) if c.ID != "" { t.Errorf("Unmarshalled object should have empty ID, received %q", c.ID) } if c.Type != "" { t.Errorf("Unmarshalled object should have empty Type, received %q", c.Type) } if c.AttributedTo != nil { t.Errorf("Unmarshalled object should have empty AttributedTo, received %q", c.AttributedTo) } if len(c.Name) != 0 { t.Errorf("Unmarshalled object should have empty Name, received %q", c.Name) } if len(c.Summary) != 0 { t.Errorf("Unmarshalled object should have empty Summary, received %q", c.Summary) } if len(c.Content) != 0 { t.Errorf("Unmarshalled object should have empty Content, received %q", c.Content) } if c.TotalItems != 0 { t.Errorf("Unmarshalled object should have empty TotalItems, received %d", c.TotalItems) } if len(c.OrderedItems) > 0 { t.Errorf("Unmarshalled object should have empty OrderedItems, received %v", c.OrderedItems) } if c.URL != nil { t.Errorf("Unmarshalled object should have empty URL, received %v", c.URL) } if !c.Published.IsZero() { t.Errorf("Unmarshalled object should have empty Published, received %q", c.Published) } if !c.StartTime.IsZero() { t.Errorf("Unmarshalled object should have empty StartTime, received %q", c.StartTime) } if !c.Updated.IsZero() { t.Errorf("Unmarshalled object should have empty Updated, received %q", c.Updated) } } func TestOrderedCollectionPage_UnmarshalJSON(t *testing.T) { p := OrderedCollectionPage{} dataEmpty := []byte("{}") p.UnmarshalJSON(dataEmpty) if p.ID != "" { t.Errorf("Unmarshalled object should have empty ID, received %q", p.ID) } if p.Type != "" { t.Errorf("Unmarshalled object should have empty Type, received %q", p.Type) } if p.AttributedTo != nil { t.Errorf("Unmarshalled object should have empty AttributedTo, received %q", p.AttributedTo) } if len(p.Name) != 0 { t.Errorf("Unmarshalled object should have empty Name, received %q", p.Name) } if len(p.Summary) != 0 { t.Errorf("Unmarshalled object should have empty Summary, received %q", p.Summary) } if len(p.Content) != 0 { t.Errorf("Unmarshalled object should have empty Content, received %q", p.Content) } if p.TotalItems != 0 { t.Errorf("Unmarshalled object should have empty TotalItems, received %d", p.TotalItems) } if len(p.OrderedItems) > 0 { t.Errorf("Unmarshalled object should have empty OrderedItems, received %v", p.OrderedItems) } if p.URL != nil { t.Errorf("Unmarshalled object should have empty URL, received %v", p.URL) } if !p.Published.IsZero() { t.Errorf("Unmarshalled object should have empty Published, received %q", p.Published) } if !p.StartTime.IsZero() { t.Errorf("Unmarshalled object should have empty StartTime, received %q", p.StartTime) } if !p.Updated.IsZero() { t.Errorf("Unmarshalled object should have empty Updated, received %q", p.Updated) } if p.PartOf != nil { t.Errorf("Unmarshalled object should have empty PartOf, received %q", p.PartOf) } if p.Current != nil { t.Errorf("Unmarshalled object should have empty Current, received %q", p.Current) } if p.First != nil { t.Errorf("Unmarshalled object should have empty First, received %q", p.First) } if p.Last != nil { t.Errorf("Unmarshalled object should have empty Last, received %q", p.Last) } if p.Next != nil { t.Errorf("Unmarshalled object should have empty Next, received %q", p.Next) } if p.Prev != nil { t.Errorf("Unmarshalled object should have empty Prev, received %q", p.Prev) } } func TestOrderedCollectionPage_Append(t *testing.T) { id := ObjectID("test") val := Object{ID: ObjectID("grrr")} c := OrderedCollectionNew(id) p := OrderedCollectionPageNew(c) p.Append(val) if p.PartOf != c.GetLink() { t.Errorf("OrderedCollection page should point to OrderedCollection %q", c.GetLink()) } if p.TotalItems != 1 { t.Errorf("OrderedCollection page of %q should have exactly one element", *p.GetID()) } if !reflect.DeepEqual(p.OrderedItems[0], val) { t.Errorf("First item in Inbox is does not match %q", val.ID) } }
-
-
activitystreams/item.go (deleted)
-
@@ -1,58 +0,0 @@package activitystreams // ItemCollection represents an array of items type ItemCollection []Item // Item struct type Item ObjectOrLink // GetID returns the ObjectID corresponding to ItemCollection func (i ItemCollection) GetID() *ObjectID { return nil } // GetLink returns the empty IRI func (i ItemCollection) GetLink() IRI { return IRI("") } // GetType returns the ItemCollection's type func (i ItemCollection) GetType() ActivityVocabularyType { return i.First().GetType() } // IsLink returns false for an ItemCollection object func (i ItemCollection) IsLink() bool { return false } // IsObject returns true for a ItemCollection object func (i ItemCollection) IsObject() bool { return false } // Append facilitates adding elements to Item arrays // and ensures ItemCollection implements the Collection interface func (i *ItemCollection) Append(o Item) error { oldLen := len(*i) d := make(ItemCollection, oldLen+1) for k, it := range *i { d[k] = it } d[oldLen] = o *i = d return nil } // First returns the ObjectID corresponding to ItemCollection func (i ItemCollection) First() Item { if len(i) == 0 { return nil } return i[0] } // Collection returns the current object as collection interface func (i *ItemCollection) Collection() CollectionInterface { return i }
-
-
activitystreams/item_test.go (deleted)
-
@@ -1,35 +0,0 @@package activitystreams import "testing" func TestItemCollection_Append(t *testing.T) { } func TestItemCollection_Collection(t *testing.T) { } func TestItemCollection_GetID(t *testing.T) { } func TestItemCollection_GetLink(t *testing.T) { } func TestItemCollection_GetType(t *testing.T) { } func TestItemCollection_IsLink(t *testing.T) { } func TestItemCollection_IsObject(t *testing.T) { } func TestItemCollection_First(t *testing.T) { }
-
-
activitystreams/link.go (deleted)
-
@@ -1,142 +0,0 @@package activitystreams var validLinkTypes = [...]ActivityVocabularyType{ MentionType, } // A Link is an indirect, qualified reference to a resource identified by a URL. // The fundamental model for links is established by [ RFC5988]. // Many of the properties defined by the Activity Vocabulary allow values that are either instances of APObject or Link. // When a Link is used, it establishes a qualified relation connecting the subject // (the containing object) to the resource identified by the href. // Properties of the Link are properties of the reference as opposed to properties of the resource. type Link struct { // Provides the globally unique identifier for an APObject or Link. ID ObjectID `jsonld:"id,omitempty"` // Identifies the APObject or Link type. Multiple values may be specified. Type ActivityVocabularyType `jsonld:"type,omitempty"` // A simple, human-readable, plain-text name for the object. // HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged values. Name NaturalLanguageValue `jsonld:"name,omitempty,collapsible"` // A link relation associated with a Link. The value must conform to both the [HTML5] and // [RFC5988](https://tools.ietf.org/html/rfc5988) "link relation" definitions. // In the [HTML5], any string not containing the "space" U+0020, "tab" (U+0009), "LF" (U+000A), // "FF" (U+000C), "CR" (U+000D) or "," (U+002C) characters can be used as a valid link relation. Rel *Link `jsonld:"rel,omitempty"` // When used on a Link, identifies the MIME media type of the referenced resource. MediaType MimeType `jsonld:"mediaType,omitempty"` // On a Link, specifies a hint as to the rendering height in device-independent pixels of the linked resource. Height uint `jsonld:"height,omitempty"` // On a Link, specifies a hint as to the rendering width in device-independent pixels of the linked resource. Width uint `jsonld:"width,omitempty"` // Identifies an entity that provides a preview of this object. Preview Item `jsonld:"preview,omitempty"` // The target resource pointed to by a Link. Href IRI `jsonld:"href,omitempty"` // Hints as to the language used by the target resource. // Value must be a [BCP47](https://tools.ietf.org/html/bcp47) Language-Tag. HrefLang LangRef `jsonld:"hrefLang,omitempty"` } // Mention is a specialized Link that represents an @mention. type Mention Link // ValidLinkType validates a type against the valid link types func ValidLinkType(typ ActivityVocabularyType) bool { for _, v := range validLinkTypes { if v == typ { return true } } return false } // LinkNew initializes a new Link func LinkNew(id ObjectID, typ ActivityVocabularyType) *Link { if !ValidLinkType(typ) { typ = LinkType } return &Link{ID: id, Type: typ} } // MentionNew initializes a new Mention func MentionNew(id ObjectID) *Mention { return &Mention{ID: id, Type: MentionType} } // IsLink validates if current Link is a Link func (l Link) IsLink() bool { return l.Type == LinkType || ValidLinkType(l.Type) } // IsObject validates if current Link is an GetID func (l Link) IsObject() bool { return l.Type == ObjectType || ValidObjectType(l.Type) } // GetID returns the ObjectID corresponding to the Link object func (l Link) GetID() *ObjectID { return &l.ID } // GetLink returns the IRI corresponding to the current Link func (l Link) GetLink() IRI { return IRI(l.ID) } // GetType returns the Type corresponding to the Mention object func (l Link) GetType() ActivityVocabularyType { return l.Type } // IsLink validates if current Mention is a Link func (m Mention) IsLink() bool { return m.Type == MentionType || ValidLinkType(m.Type) } // IsObject validates if current Mention is an GetID func (m Mention) IsObject() bool { return m.Type == ObjectType || ValidObjectType(m.Type) } // GetID returns the ObjectID corresponding to the Mention object func (m Mention) GetID() *ObjectID { return Link(m).GetID() } // GetLink returns the IRI corresponding to the current Mention func (m Mention) GetLink() IRI { return IRI(m.ID) } // GetType returns the Type corresponding to the Mention object func (m Mention) GetType() ActivityVocabularyType { return m.Type } // UnmarshalJSON func (l *Link) UnmarshalJSON(data []byte) error { l.ID = getAPObjectID(data) l.Type = getAPType(data) l.MediaType = getAPMimeType(data) l.Name = getAPNaturalLanguageField(data, "name") l.HrefLang = getAPLangRefField(data, "hrefLang") u := getURIField(data, "href") if u != nil && !u.IsObject() { l.Href = u.GetLink() } //fmt.Printf("%s\n %#v", data, l) return nil } // UnmarshalJSON func (m *Mention) UnmarshalJSON(data []byte) error { l := Link{} err := l.UnmarshalJSON(data) *m = Mention(l) return err }
-
-
activitystreams/link_test.go (deleted)
-
@@ -1,111 +0,0 @@package activitystreams import ( "reflect" "testing" ) func TestLinkNew(t *testing.T) { var testValue = ObjectID("test") var testType ActivityVocabularyType l := LinkNew(testValue, testType) if l.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", l.ID, testValue) } if l.Type != LinkType { t.Errorf("APObject Type '%v' different than expected '%v'", l.Type, LinkType) } } func TestValidLinkType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidLinkType(LinkType) { t.Errorf("Generic Link Type '%v' should not be valid", LinkType) } if ValidLinkType(invalidType) { t.Errorf("Link Type '%v' should not be valid", invalidType) } for _, validType := range validLinkTypes { if !ValidLinkType(validType) { t.Errorf("Link Type '%v' should be valid", validType) } } } func TestLink_IsLink(t *testing.T) { l := LinkNew("test", LinkType) if !l.IsLink() { t.Errorf("%#v should be a valid link", l.Type) } m := LinkNew("test", MentionType) if !m.IsLink() { t.Errorf("%#v should be a valid link", m.Type) } } func TestLink_IsObject(t *testing.T) { l := LinkNew("test", LinkType) if l.IsObject() { t.Errorf("%#v should not be a valid object", l.Type) } m := LinkNew("test", MentionType) if m.IsObject() { t.Errorf("%#v should not be a valid object", m.Type) } } func TestMention_IsLink(t *testing.T) { m := MentionNew("test") if !m.IsLink() { t.Errorf("%#v should be a valid Mention", m.Type) } } func TestMention_IsObject(t *testing.T) { m := MentionNew("test") if m.IsObject() { t.Errorf("%#v should not be a valid object", m.Type) } } func TestMention_Object(t *testing.T) { m := MentionNew("test") if !reflect.DeepEqual(ObjectID("test"), *m.GetID()) { t.Errorf("%#v should be an empty object", m.GetID()) } } func TestLink_GetID(t *testing.T) { } func TestLink_GetLink(t *testing.T) { } func TestLink_GetType(t *testing.T) { } func TestLink_UnmarshalJSON(t *testing.T) { } func TestMention_GetID(t *testing.T) { } func TestMention_GetLink(t *testing.T) { } func TestMention_GetType(t *testing.T) { } func TestMentionNew(t *testing.T) { }
-
-
activitystreams/object.go (deleted)
-
@@ -1,574 +0,0 @@package activitystreams import ( "encoding/json" "fmt" "sort" "strings" "time" "github.com/buger/jsonparser" ) // ObjectID designates an unique global identifier. // All Objects in [ActivityStreams] should have unique global identifiers. // ActivityPub extends this requirement; all objects distributed by the ActivityPub protocol MUST // have unique global identifiers, unless they are intentionally transient // (short lived activities that are not intended to be able to be looked up, // such as some kinds of chat messages or game notifications). // These identifiers must fall into one of the following groups: // // 1. Publicly dereferencable URIs, such as HTTPS URIs, with their authority belonging // to that of their originating server. (Publicly facing content SHOULD use HTTPS URIs). // 2. An ID explicitly specified as the JSON null object, which implies an anonymous object // (a part of its parent context) type ObjectID IRI const ( // ActivityBaseURI the basic URI for the activity streams namespaces ActivityBaseURI = IRI("https://www.w3.org/ns/activitystreams") ObjectType ActivityVocabularyType = "Object" LinkType ActivityVocabularyType = "Link" ActivityType ActivityVocabularyType = "Activity" IntransitiveActivityType ActivityVocabularyType = "IntransitiveActivity" ActorType ActivityVocabularyType = "Actor" CollectionType ActivityVocabularyType = "Collection" OrderedCollectionType ActivityVocabularyType = "OrderedCollection" CollectionPageType ActivityVocabularyType = "CollectionPage" OrderedCollectionPageType ActivityVocabularyType = "OrderedCollectionPage" // Activity Pub Object Types ArticleType ActivityVocabularyType = "Article" AudioType ActivityVocabularyType = "Audio" DocumentType ActivityVocabularyType = "Document" EventType ActivityVocabularyType = "Event" ImageType ActivityVocabularyType = "Image" NoteType ActivityVocabularyType = "Note" PageType ActivityVocabularyType = "Page" PlaceType ActivityVocabularyType = "Place" ProfileType ActivityVocabularyType = "Profile" RelationshipType ActivityVocabularyType = "Relationship" TombstoneType ActivityVocabularyType = "Tombstone" VideoType ActivityVocabularyType = "Video" // MentionType is a link type for @mentions MentionType ActivityVocabularyType = "Mention" ) const ( NilLangRef LangRef = "-" ) var validGenericObjectTypes = [...]ActivityVocabularyType{ ActivityType, IntransitiveActivityType, ObjectType, ActorType, CollectionType, OrderedCollectionType, } var validGenericLinkTypes = [...]ActivityVocabularyType{ LinkType, } var validGenericTypes = append(validGenericObjectTypes[:], validGenericLinkTypes[:]...) var validObjectTypes = [...]ActivityVocabularyType{ ArticleType, AudioType, DocumentType, EventType, ImageType, NoteType, PageType, PlaceType, ProfileType, RelationshipType, TombstoneType, VideoType, } type ( // ActivityVocabularyType is the data type for an Activity type object ActivityVocabularyType string // ActivityObject is a subtype of Object that describes some form of action that may happen, // is currently happening, or has already happened ActivityObject interface { GetID() *ObjectID } // Item describes an object of any kind. ObjectOrLink interface { ActivityObject LinkOrURI GetType() ActivityVocabularyType IsLink() bool IsObject() bool //UnmarshalJSON([]byte) error } // LinkOrURI is an interface that Object and Link structs implement, and at the same time // they are kept disjointed LinkOrURI interface { GetLink() IRI } // MimeType is the type for MIME types MimeType string // LangRef is the type for a language reference, should be ISO 639-1 language specifier. LangRef string LangRefValue struct { Ref LangRef Value string } // NaturalLanguageValue is a mapping for multiple language values NaturalLanguageValue []LangRefValue ) func NaturalLanguageValueNew() NaturalLanguageValue { return make(NaturalLanguageValue, 0) } func (n NaturalLanguageValue) Get(ref LangRef) string { for _, val := range n { if val.Ref == ref { return val.Value } } return "" } func (n *NaturalLanguageValue) Set(ref LangRef, v string) error { t := append(*n, LangRefValue{ref, v}) *n = t return nil } // IsLink validates if currentActivity Pub Object is a Link func (o Object) IsLink() bool { return false } // IsObject validates if currentActivity Pub Object is an Object func (o Object) IsObject() bool { return true } // MarshalJSON serializes the NaturalLanguageValue into JSON func (n NaturalLanguageValue) MarshalJSON() ([]byte, error) { if len(n) == 0 { return json.Marshal(nil) } if len(n) == 1 { for _, v := range n { return json.Marshal(v.Value) } } mm := make(map[LangRef]string) for _, val := range n { mm[val.Ref] = val.Value } return json.Marshal(mm) } // First returns the first element in the map func (n NaturalLanguageValue) First() string { for _, v := range n { return v.Value } return "" } // MarshalText serializes the NaturalLanguageValue into Text func (n NaturalLanguageValue) MarshalText() ([]byte, error) { for _, v := range n { return []byte(fmt.Sprintf("%q", v)), nil } return nil, nil } // Append is syntactic sugar for resizing the NaturalLanguageValue map // and appending an element func (n *NaturalLanguageValue) Append(lang LangRef, value string) error { var t NaturalLanguageValue if len(*n) == 0 { t = make(NaturalLanguageValue, 1) } else { t = *n } t = append(*n, LangRefValue{lang, value}) *n = t return nil } // UnmarshalJSON tries to load the NaturalLanguage array from the incoming json value func (l *LangRef) UnmarshalJSON(data []byte) error { return l.UnmarshalText(data) } // UnmarshalText tries to load the NaturalLanguage array from the incoming Text value func (l *LangRef) UnmarshalText(data []byte) error { *l = LangRef("") if len(data) == 0 { return nil } if len(data) > 2 { if data[0] == '"' && data[len(data)-1] == '"' { *l = LangRef(data[1 : len(data)-1]) } } else { *l = LangRef(data) } return nil } // UnmarshalJSON tries to load the NaturalLanguage array from the incoming json value func (n *NaturalLanguageValue) UnmarshalJSON(data []byte) error { val, typ, _, err := jsonparser.Get(data) if err != nil { // try our luck if data contains an unquoted string n.Append(NilLangRef, string(data)) return nil } switch typ { case jsonparser.Object: jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { n.Append(LangRef(key), string(value)) return err }) case jsonparser.String: n.Append(NilLangRef, string(val)) } return nil } // UnmarshalText tries to load the NaturalLanguage array from the incoming Text value func (n *NaturalLanguageValue) UnmarshalText(data []byte) error { if data[0] == '"' { // a quoted string - loading it to c.URL if data[len(data)-1] != '"' { return fmt.Errorf("invalid string value when unmarshalling %T value", n) } n.Append(LangRef(NilLangRef), string(data[1:len(data)-1])) } return nil } type object struct { // ID provides the globally unique identifier for anActivity Pub Object or Link. ID ObjectID `jsonld:"id,omitempty"` // Type identifies the Activity Pub Object or Link type. Multiple values may be specified. Type ActivityVocabularyType `jsonld:"type,omitempty"` // Name a simple, human-readable, plain-text name for the object. // HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged values. Name NaturalLanguageValue `jsonld:"name,omitempty,collapsible"` // Attachment identifies a resource attached or related to an object that potentially requires special handling. // The intent is to provide a model that is at least semantically similar to attachments in email. Attachment Item `jsonld:"attachment,omitempty"` // AttributedTo identifies one or more entities to which this object is attributed. The attributed entities might not be Actors. // For instance, an object might be attributed to the completion of another activity. AttributedTo Item `jsonld:"attributedTo,omitempty"` // Audience identifies one or more entities that represent the total population of entities // for which the object can considered to be relevant. Audience Item `jsonld:"audience,omitempty"` // Content or textual representation of the Activity Pub Object encoded as a JSON string. // By default, the value of content is HTML. // The mediaType property can be used in the object to indicate a different content type. // (The content MAY be expressed using multiple language-tagged values.) Content NaturalLanguageValue `jsonld:"content,omitempty,collapsible"` // Context identifies the context within which the object exists or an activity was performed. // The notion of "context" used is intentionally vague. // The intended function is to serve as a means of grouping objects and activities that share a // common originating context or purpose. An example could be all activities relating to a common project or event. Context Item `jsonld:"context,omitempty"` // MediaType when used on an Object, identifies the MIME media type of the value of the content property. // If not specified, the content property is assumed to contain text/html content. MediaType MimeType `jsonld:"mediaType,omitempty"` // EndTime the date and time describing the actual or expected ending time of the object. // When used with an Activity object, for instance, the endTime property specifies the moment // the activity concluded or is expected to conclude. EndTime time.Time `jsonld:"endTime,omitempty"` // Generator identifies the entity (e.g. an application) that generated the object. Generator Item `jsonld:"generator,omitempty"` // Icon indicates an entity that describes an icon for this object. // The image should have an aspect ratio of one (horizontal) to one (vertical) // and should be suitable for presentation at a small size. Icon Item `jsonld:"icon,omitempty"` // Image indicates an entity that describes an image for this object. // Unlike the icon property, there are no aspect ratio or display size limitations assumed. Image Item `jsonld:"image,omitempty"` // InReplyTo indicates one or more entities for which this object is considered a response. InReplyTo Item `jsonld:"inReplyTo,omitempty"` // Location indicates one or more physical or logical locations associated with the object. Location Item `jsonld:"location,omitempty"` // Preview identifies an entity that provides a preview of this object. Preview Item `jsonld:"preview,omitempty"` // Published the date and time at which the object was published Published time.Time `jsonld:"published,omitempty"` // Replies identifies a Collection containing objects considered to be responses to this object. Replies Item `jsonld:"replies,omitempty"` // StartTime the date and time describing the actual or expected starting time of the object. // When used with an Activity object, for instance, the startTime property specifies // the moment the activity began or is scheduled to begin. StartTime time.Time `jsonld:"startTime,omitempty"` // Summary a natural language summarization of the object encoded as HTML. // *Multiple language tagged summaries may be provided.) Summary NaturalLanguageValue `jsonld:"summary,omitempty,collapsible"` // Tag one or more "tags" that have been associated with an objects. A tag can be any kind of Activity Pub Object. // The key difference between attachment and tag is that the former implies association by inclusion, // while the latter implies associated by reference. Tag ItemCollection `jsonld:"tag,omitempty"` // Updated the date and time at which the object was updated Updated time.Time `jsonld:"updated,omitempty"` // URL identifies one or more links to representations of the object URL LinkOrURI `jsonld:"url,omitempty"` // To identifies an entity considered to be part of the public primary audience of an Activity Pub Object To ItemCollection `jsonld:"to,omitempty"` // Bto identifies anActivity Pub Object that is part of the private primary audience of this Activity Pub Object. Bto ItemCollection `jsonld:"bto,omitempty"` // CC identifies anActivity Pub Object that is part of the public secondary audience of this Activity Pub Object. CC ItemCollection `jsonld:"cc,omitempty"` // BCC identifies one or more Objects that are part of the private secondary audience of this Activity Pub Object. BCC ItemCollection `jsonld:"bcc,omitempty"` // Duration when the object describes a time-bound resource, such as an audio or video, a meeting, etc, // the duration property indicates the object's approximate duration. // The value must be expressed as an xsd:duration as defined by [ xmlschema11-2], // section 3.3.6 (e.g. a period of 5 seconds is represented as "PT5S"). Duration time.Duration `jsonld:"duration,omitempty"` } type ( Parent = object // Describes an object of any kind. // The Activity Pub Object type serves as the base type for most of the other kinds of objects defined in the Activity Vocabulary, // including other Core types such as Activity, IntransitiveActivity, Collection and OrderedCollection. Object = object // Article represents any kind of multi-paragraph written work. Article Object // Audio represents an audio document of any kind. Audio Document // Document represents a document of any kind. Document Object // Event represents any kind of event. Event Object // Image An image document of any kind Image Document // Note represents a short written work typically less than a single paragraph in length. Note Object // Page represents a Web Page. Page Document // Video represents a video document of any kind Video Document ) // Place represents a logical or physical location. See 5.3 Representing Places for additional information. type Place struct { Parent // Accuracy indicates the accuracy of position coordinates on a Place objects. // Expressed in properties of percentage. e.g. "94.0" means "94.0% accurate". Accuracy float32 // Altitude indicates the altitude of a place. The measurement units is indicated using the units property. // If units is not specified, the default is assumed to be "m" indicating meters. Altitude float32 // Latitude the latitude of a place Latitude float32 // Longitude the longitude of a place Longitude float32 // Radius the radius from the given latitude and longitude for a Place. // The units is expressed by the units property. If units is not specified, // the default is assumed to be "m" indicating "meters". Radius int // Specifies the measurement units for the radius and altitude properties on a Place object. // If not specified, the default is assumed to be "m" for "meters". // Values "cm" | " feet" | " inches" | " km" | " m" | " miles" | xsd:anyURI Units string } // Profile a Profile is a content object that describes another Object, // typically used to describe Actor Type objects. // The describes property is used to reference the object being described by the profile. type Profile struct { Parent // Describes On a Profile object, the describes property identifies the object described by the Profile. Describes Item `jsonld:"describes,omitempty"` } // Relationship describes a relationship between two individuals. // The subject and object properties are used to identify the connected individuals. //See 5.2 Representing Relationships Between Entities for additional information. // 5.2: The relationship property specifies the kind of relationship that exists between the two individuals identified // by the subject and object properties. Used together, these three properties form what is commonly known // as a "reified statement" where subject identifies the subject, relationship identifies the predicate, // and object identifies the object. type Relationship struct { Parent // Subject Subject On a Relationship object, the subject property identifies one of the connected individuals. // For instance, for a Relationship object describing "John is related to Sally", subject would refer to John. Subject Item // Object Object Item // Relationship On a Relationship object, the relationship property identifies the kind // of relationship that exists between subject and object. Relationship Item } // Tombstone a Tombstone represents a content object that has been deleted. // It can be used in Collections to signify that there used to be an object at this position, // but it has been deleted. type Tombstone struct { Parent // FormerType On a Tombstone object, the formerType property identifies the type of the object that was deleted. FormerType ActivityVocabularyType `jsonld:"formerType,omitempty"` // Deleted On a Tombstone object, the deleted property is a timestamp for when the object was deleted. Deleted time.Time `jsonld:"deleted,omitempty"` } // ValidGenericType validates the type against the valid generic object types func ValidGenericType(typ ActivityVocabularyType) bool { for _, v := range validGenericObjectTypes { if v == typ { return true } } return false } // ValidObjectType validates the type against the valid object types func ValidObjectType(typ ActivityVocabularyType) bool { for _, v := range validObjectTypes { if v == typ { return true } } return ValidActivityType(typ) || ValidActorType(typ) || ValidCollectionType(typ) || ValidGenericType(typ) } // ObjectNew initializes a new Object func ObjectNew(typ ActivityVocabularyType) *Object { if !(ValidObjectType(typ)) { typ = ObjectType } o := Object{Type: typ} o.Name = NaturalLanguageValueNew() o.Content = NaturalLanguageValueNew() return &o } // GetID returns the ObjectID corresponding to the current object func (o Object) GetID() *ObjectID { return &o.ID } // GetLink returns the IRI corresponding to the current object func (o Object) GetLink() IRI { return IRI(o.ID) } // Link returns the Link corresponding to the current object func (o Object) GetType() ActivityVocabularyType { return o.Type } // recipientsDeduplication normalizes the received arguments lists func recipientsDeduplication(recArgs ...*ItemCollection) error { recIds := make([]ObjectID, 0) for _, recList := range recArgs { if recList == nil { continue } toRemove := make([]int, 0) for i, rec := range *recList { save := true if rec == nil { continue } var testId ObjectID if rec.IsObject() { testId = *rec.GetID() } else if rec.IsLink() { testId = ObjectID(rec.(IRI)) } else { continue } for _, id := range recIds { if testId == id { // mark the element for removal toRemove = append(toRemove, i) save = false } } if save { recIds = append(recIds, testId) } } sort.Sort(sort.Reverse(sort.IntSlice(toRemove))) for _, idx := range toRemove { *recList = append((*recList)[:idx], (*recList)[idx+1:]...) } } return nil } // UnmarshalJSON func (i *ObjectID) UnmarshalJSON(data []byte) error { *i = ObjectID(strings.Trim(string(data), "\"")) return nil } // UnmarshalJSON func (c *MimeType) UnmarshalJSON(data []byte) error { *c = MimeType(strings.Trim(string(data), "\"")) return nil } // UnmarshalJSON func (o *Object) UnmarshalJSON(data []byte) error { o.ID = getAPObjectID(data) o.Type = getAPType(data) o.Name = getAPNaturalLanguageField(data, "name") o.Content = getAPNaturalLanguageField(data, "content") o.Summary = getAPNaturalLanguageField(data, "summary") o.Context = getAPItem(data, "context") o.URL = getURIField(data, "url") o.MediaType = MimeType(getAPString(data, "mediaType")) o.Generator = getAPItem(data, "generator") o.AttributedTo = getAPItem(data, "attributedTo") o.InReplyTo = getAPItem(data, "inReplyTo") o.Published = getAPTime(data, "published") o.StartTime = getAPTime(data, "startTime") o.EndTime = getAPTime(data, "endTime") o.Duration = getAPDuration(data, "duration") o.Icon = getAPItem(data, "icon") o.Image = getAPItem(data, "image") o.Updated = getAPTime(data, "updated") to := getAPItems(data, "to") if to != nil { o.To = to } bto := getAPItems(data, "bto") if bto != nil { o.Bto = bto } cc := getAPItems(data, "cc") if cc != nil { o.CC = cc } bcc := getAPItems(data, "bcc") if bcc != nil { o.BCC = bcc } replies := getAPItem(data, "replies") if replies != nil { o.Replies = replies } tag := getAPItems(data, "tag") if tag != nil { o.Tag = tag } return nil }
-
-
activitystreams/object_test.go (deleted)
-
@@ -1,466 +0,0 @@package activitystreams import ( "reflect" "testing" ) func TestObjectNew(t *testing.T) { var testValue = ObjectID("test") var testType = ArticleType o := ObjectNew(testType) o.ID = testValue if o.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", o.ID, testValue) } if o.Type != testType { t.Errorf("APObject Type '%v' different than expected '%v'", o.Type, testType) } n := ObjectNew("") n.ID = testValue if n.ID != testValue { t.Errorf("APObject Id '%v' different than expected '%v'", n.ID, testValue) } if n.Type != ObjectType { t.Errorf("APObject Type '%v' different than expected '%v'", n.Type, ObjectType) } } func TestValidGenericType(t *testing.T) { for _, validType := range validGenericObjectTypes { if !ValidObjectType(validType) { t.Errorf("Generic Type '%v' should be valid", validType) } } } func TestValidObjectType(t *testing.T) { var invalidType ActivityVocabularyType = "RandomType" if ValidObjectType(invalidType) { t.Errorf("APObject Type '%v' should not be valid", invalidType) } for _, validType := range validObjectTypes { if !ValidObjectType(validType) { t.Errorf("APObject Type '%v' should be valid", validType) } } } func TestMarshalJSON(t *testing.T) { m := NaturalLanguageValue{ { "en", "test", }, { "de", "test", }, } result, err := m.MarshalJSON() if err != nil { t.Errorf("Failed marshaling '%v'", err) } mRes := "{\"de\":\"test\",\"en\":\"test\"}" if string(result) != mRes { t.Errorf("Different results '%v' vs. '%v'", string(result), mRes) } //n := NaturalLanguageValueNew() //result, err := n.MarshalJSON() s := make(map[LangRef]string) s["en"] = "test" n1 := NaturalLanguageValue{{ "en", "test", }} result1, err1 := n1.MarshalJSON() if err1 != nil { t.Errorf("Failed marshaling '%v'", err1) } mRes1 := "\"test\"" if string(result1) != mRes1 { t.Errorf("Different results '%v' vs. '%v'", string(result1), mRes1) } } func TestNaturalLanguageValue_MarshalJSON(t *testing.T) { p := NaturalLanguageValue{ { "en", "the test", }, { "fr", "le test", }, } js := "{\"en\":\"the test\",\"fr\":\"le test\"}" out, err := p.MarshalJSON() if err != nil { t.Errorf("Error: '%s'", err) } if js != string(out) { t.Errorf("Different marshal result '%s', instead of '%s'", out, js) } p1 := NaturalLanguageValue{ { "en", "the test", }, } out1, err1 := p1.MarshalJSON() if err1 != nil { t.Errorf("Error: '%s'", err1) } txt := "\"the test\"" if txt != string(out1) { t.Errorf("Different marshal result '%s', instead of '%s'", out1, txt) } } func TestObject_IsLink(t *testing.T) { o := ObjectNew(ObjectType) o.ID = "test" if o.IsLink() { t.Errorf("%#v should not be a valid link", o.Type) } m := ObjectNew(AcceptType) m.ID = "test" if m.IsLink() { t.Errorf("%#v should not be a valid link", m.Type) } } func TestObject_IsObject(t *testing.T) { o := ObjectNew(ObjectType) o.ID = "test" if !o.IsObject() { t.Errorf("%#v should be a valid object", o.Type) } m := ObjectNew(AcceptType) m.ID = "test" if !m.IsObject() { t.Errorf("%#v should be a valid object", m.Type) } } func TestObjectsArr_Append(t *testing.T) { d := make(ItemCollection, 0) val := Object{ID: ObjectID("grrr")} d.Append(val) if len(d) != 1 { t.Errorf("Objects array should have exactly an element") } if !reflect.DeepEqual(d[0], val) { t.Errorf("First item in object array does not match %q", val.ID) } } func TestRecipientsDeduplication(t *testing.T) { bob := PersonNew("bob") alice := PersonNew("alice") foo := OrganizationNew("foo") bar := GroupNew("bar") first := make(ItemCollection, 0) if len(first) != 0 { t.Errorf("Objects array should have exactly an element") } first.Append(bob) first.Append(alice) first.Append(foo) first.Append(bar) if len(first) != 4 { t.Errorf("Objects array should have exactly 4(four) elements, not %d", len(first)) } first.Append(bar) first.Append(alice) first.Append(foo) first.Append(bob) if len(first) != 8 { t.Errorf("Objects array should have exactly 8(eight) elements, not %d", len(first)) } recipientsDeduplication(&first) if len(first) != 4 { t.Errorf("Objects array should have exactly 4(four) elements, not %d", len(first)) } second := make(ItemCollection, 0) second.Append(bar) second.Append(foo) recipientsDeduplication(&first, &second) if len(first) != 4 { t.Errorf("First Objects array should have exactly 8(eight) elements, not %d", len(first)) } if len(second) != 0 { t.Errorf("Second Objects array should have exactly 0(zero) elements, not %d", len(second)) } err := recipientsDeduplication(&first, &second, nil) if err != nil { t.Errorf("Deduplication with empty array failed") } } func TestNaturalLanguageValue_Get(t *testing.T) { testVal := "test" a := NaturalLanguageValue{{NilLangRef, testVal}} if a.Get(NilLangRef) != testVal { t.Errorf("Invalid Get result. Expected %s received %s", testVal, a.Get(NilLangRef)) } } func TestNaturalLanguageValue_Set(t *testing.T) { testVal := "test" a := NaturalLanguageValue{{NilLangRef, "ana are mere"}} err := a.Set(LangRef("en"), testVal) if err != nil { t.Errorf("Received error when doing Set %s", err) } } func TestNaturalLanguageValue_Append(t *testing.T) { var a NaturalLanguageValue if len(a) != 0 { t.Errorf("Invalid initialization of %T. Size %d > 0 ", a, len(a)) } langEn := LangRef("en") valEn := "random value" a.Append(langEn, valEn) if len(a) != 1 { t.Errorf("Invalid append of one element to %T. Size %d != 1", a, len(a)) } if a.Get(langEn) != valEn { t.Errorf("Invalid append of one element to %T. Value of %q not equal to %q, but %q", a, langEn, valEn, a.Get(langEn)) } langDe := LangRef("de") valDe := "randomisch" a.Append(langDe, valDe) if len(a) != 2 { t.Errorf("Invalid append of one element to %T. Size %d != 2", a, len(a)) } if a.Get(langEn) != valEn { t.Errorf("Invalid append of one element to %T. Value of %q not equal to %q, but %q", a, langEn, valEn, a.Get(langEn)) } if a.Get(langDe) != valDe { t.Errorf("Invalid append of one element to %T. Value of %q not equal to %q, but %q", a, langDe, valDe, a.Get(langDe)) } } func TestLangRef_UnmarshalJSON(t *testing.T) { lang := "en-US" json := `"` + lang + `"` var a LangRef a.UnmarshalJSON([]byte(json)) if string(a) != lang { t.Errorf("Invalid json unmarshal for %T. Expected %q, found %q", lang, lang, string(a)) } } func TestNaturalLanguageValue_UnmarshalFullObjectJSON(t *testing.T) { langEn := "en-US" valEn := "random" langDe := "de-DE" valDe := "zufällig\\n" //m := make(map[string]string) //m[langEn] = valEn //m[langDe] = valDe json := `{ "` + langEn + `": "` + valEn + `", "` + langDe + `": "` + valDe + `" }` var a NaturalLanguageValue a.Append(LangRef(langEn), valEn) a.Append(LangRef(langDe), valDe) err := a.UnmarshalJSON([]byte(json)) if err != nil { t.Error(err) } for lang, val := range a { if val.Ref != LangRef(langEn) && val.Ref != LangRef(langDe) { t.Errorf("Invalid json unmarshal for %T. Expected lang %q or %q, found %q", a, langEn, langDe, lang) } if val.Ref == LangRef(langEn) && val.Value != valEn { t.Errorf("Invalid json unmarshal for %T. Expected value %q, found %q", a, valEn, val) } if val.Ref == LangRef(langDe) && val.Value != valDe { t.Errorf("Invalid json unmarshal for %T. Expected value %q, found %q", a, valDe, val) } } } func validateEmptyObject(o Object, t *testing.T) { if o.ID != "" { t.Errorf("Unmarshalled object %T should have empty ID, received %q", o, o.ID) } if o.Type != "" { t.Errorf("Unmarshalled object %T should have empty Type, received %q", o, o.Type) } if o.AttributedTo != nil { t.Errorf("Unmarshalled object %T should have empty AttributedTo, received %q", o, o.AttributedTo) } if len(o.Name) != 0 { t.Errorf("Unmarshalled object %T should have empty Name, received %q", o, o.Name) } if len(o.Summary) != 0 { t.Errorf("Unmarshalled object %T should have empty Summary, received %q", o, o.Summary) } if len(o.Content) != 0 { t.Errorf("Unmarshalled object %T should have empty Content, received %q", o, o.Content) } if o.URL != nil { t.Errorf("Unmarshalled object %T should have empty URL, received %v", o, o.URL) } if o.Icon != nil { t.Errorf("Unmarshalled object %T should have empty Icon, received %v", o, o.Icon) } if o.Image != nil { t.Errorf("Unmarshalled object %T should have empty Image, received %v", o, o.Image) } if !o.Published.IsZero() { t.Errorf("Unmarshalled object %T should have empty Published, received %q", o, o.Published) } if !o.StartTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty StartTime, received %q", o, o.StartTime) } if !o.Updated.IsZero() { t.Errorf("Unmarshalled object %T should have empty Updated, received %q", o, o.Updated) } if !o.EndTime.IsZero() { t.Errorf("Unmarshalled object %T should have empty EndTime, received %q", o, o.EndTime) } if o.Duration != 0 { t.Errorf("Unmarshalled object %T should have empty Duration, received %q", o, o.Duration) } if len(o.To) > 0 { t.Errorf("Unmarshalled object %T should have empty To, received %q", o, o.To) } if len(o.Bto) > 0 { t.Errorf("Unmarshalled object %T should have empty Bto, received %q", o, o.Bto) } if len(o.CC) > 0 { t.Errorf("Unmarshalled object %T should have empty CC, received %q", o, o.CC) } if len(o.BCC) > 0 { t.Errorf("Unmarshalled object %T should have empty BCC, received %q", o, o.BCC) } } func TestObject_UnmarshalJSON(t *testing.T) { o := Object{} dataEmpty := []byte("{}") o.UnmarshalJSON(dataEmpty) validateEmptyObject(o, t) } func TestMimeType_UnmarshalJSON(t *testing.T) { m := MimeType("") dataEmpty := []byte("") m.UnmarshalJSON(dataEmpty) if m != "" { t.Errorf("Unmarshalled object %T should be an empty string, received %q", m, m) } } func TestLangRef_UnmarshalText(t *testing.T) { l := LangRef("") dataEmpty := []byte("") l.UnmarshalText(dataEmpty) if l != "" { t.Errorf("Unmarshalled object %T should be an empty string, received %q", l, l) } } func TestObjectID_UnmarshalJSON(t *testing.T) { o := ObjectID("") dataEmpty := []byte("") o.UnmarshalJSON(dataEmpty) if o != "" { t.Errorf("Unmarshalled object %T should be an empty string, received %q", o, o) } } func TestNaturalLanguageValue_UnmarshalJSON(t *testing.T) { l := LangRef("") dataEmpty := []byte("") l.UnmarshalJSON(dataEmpty) if l != "" { t.Errorf("Unmarshalled object %T should be an empty string, received %q", l, l) } } func TestNaturalLanguageValue_UnmarshalText(t *testing.T) { l := LangRef("") dataEmpty := []byte("") l.UnmarshalText(dataEmpty) if l != "" { t.Errorf("Unmarshalled object %T should be an empty string, received %q", l, l) } } func TestObject_GetID(t *testing.T) { a := Object{} testVal := "crash$" a.ID = ObjectID(testVal) if string(*a.GetID()) != testVal { t.Errorf("%T should return %q, Received %q", a.GetID, testVal, *a.GetID()) } } func TestObject_GetLink(t *testing.T) { a := Object{} testVal := "crash$" a.ID = ObjectID(testVal) if string(a.GetLink()) != testVal { t.Errorf("%T should return %q, Received %q", a.GetLink, testVal, a.GetLink()) } } func TestObject_GetType(t *testing.T) { a := Object{} a.Type = ActorType if a.GetType() != ActorType { t.Errorf("%T should return %q, Received %q", a.GetType, ActorType, a.GetType()) } } func TestNaturalLanguageValue_First(t *testing.T) { } func TestNaturalLanguageValueNew(t *testing.T) { n := NaturalLanguageValueNew() if len(n) != 0 { t.Errorf("Initial %T should have length 0, received %d", n, len(n)) } } func TestNaturalLanguageValue_MarshalText(t *testing.T) { }
-
-
activitystreams/unmarshalling.go (deleted)
-
@@ -1,505 +0,0 @@package activitystreams import ( "encoding" "encoding/json" "fmt" "net/url" "reflect" "strings" "time" "github.com/buger/jsonparser" ) var ( apUnmarshalerType = reflect.TypeOf(new(Item)).Elem() unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem() textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() ) type mockObj map[string]json.RawMessage func getType(j json.RawMessage) ActivityVocabularyType { mock := make(mockObj, 0) json.Unmarshal([]byte(j), &mock) for key, val := range mock { if strings.ToLower(key) == "type" { return ActivityVocabularyType(strings.Trim(string(val), "\"")) } } return "" } func getAPObjectID(data []byte) ObjectID { i, err := jsonparser.GetString(data, "id") if err != nil { return ObjectID("") } return ObjectID(i) } func getAPType(data []byte) ActivityVocabularyType { t, err := jsonparser.GetString(data, "type") typ := ActivityVocabularyType(t) if err != nil { return ActivityVocabularyType("") } return typ } func getAPMimeType(data []byte) MimeType { t, err := jsonparser.GetString(data, "mediaType") if err != nil { return MimeType("") } return MimeType(t) } func getAPInt(data []byte, prop string) int64 { val, err := jsonparser.GetInt(data, prop) if err != nil { } return val } func getAPString(data []byte, prop string) string { val, err := jsonparser.GetString(data, prop) if err != nil { } return val } func getAPNaturalLanguageField(data []byte, prop string) NaturalLanguageValue { n := NaturalLanguageValue{} val, typ, _, err := jsonparser.Get(data, prop) if err != nil { return nil } switch typ { case jsonparser.Object: jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { if dataType == jsonparser.String { n.Append(LangRef(key), string(value)) } return err }) case jsonparser.String: n.Append(NilLangRef, string(val)) } return n } func getAPTime(data []byte, prop string) time.Time { t := time.Time{} str, _ := jsonparser.GetUnsafeString(data, prop) t.UnmarshalText([]byte(str)) return t } func getAPDuration(data []byte, prop string) time.Duration { str, _ := jsonparser.GetUnsafeString(data, prop) d, _ := time.ParseDuration(str) return d } func unmarshalToAPObject(data []byte) Item { if _, err := url.ParseRequestURI(string(data)); err == nil { // try to see if it's an IRI return IRI(data) } i, err := getAPObjectByType(getAPType(data)) if err != nil { return nil } p := reflect.PtrTo(reflect.TypeOf(i)) if reflect.TypeOf(i).Implements(unmarshalerType) || p.Implements(unmarshalerType) { err = i.(json.Unmarshaler).UnmarshalJSON(data) } if reflect.TypeOf(i).Implements(textUnmarshalerType) || p.Implements(textUnmarshalerType) { err = i.(encoding.TextUnmarshaler).UnmarshalText(data) } if err != nil { return nil } return i } func getAPItem(data []byte, prop string) Item { val, typ, _, err := jsonparser.Get(data, prop) if err != nil { return nil } switch typ { case jsonparser.String: if _, err = url.ParseRequestURI(string(val)); err == nil { // try to see if it's an IRI return IRI(val) } case jsonparser.Object: return unmarshalToAPObject(val) case jsonparser.Number: fallthrough case jsonparser.Array: fallthrough case jsonparser.Boolean: fallthrough case jsonparser.Null: fallthrough case jsonparser.Unknown: fallthrough default: return nil } return nil } func getAPItems(data []byte, prop string) ItemCollection { val, typ, _, err := jsonparser.Get(data, prop) if err != nil { return nil } var it ItemCollection switch typ { case jsonparser.Array: jsonparser.ArrayEach(data, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { i := unmarshalToAPObject(value) if i != nil { it.Append(i) } }, prop) case jsonparser.Object: jsonparser.ObjectEach(data, func(key []byte, value []byte, dataType jsonparser.ValueType, offset int) error { i := unmarshalToAPObject(value) if i != nil { it.Append(i) } return err }, prop) case jsonparser.String: s, _ := jsonparser.GetString(val) it.Append(IRI(s)) } return it } func getURIField(data []byte, prop string) Item { val, typ, _, err := jsonparser.Get(data, prop) if err != nil { return nil } switch typ { case jsonparser.Object: return getAPItem(data, prop) case jsonparser.Array: var it ItemCollection jsonparser.ArrayEach(val, func(value []byte, dataType jsonparser.ValueType, offset int, err error) { if _, err := url.Parse(string(value)); err == nil { it.Append(IRI(value)) return } i, err := getAPObjectByType(getAPType(value)) if err != nil { return } err = i.(json.Unmarshaler).UnmarshalJSON(value) if err != nil { return } it.Append(i) }) return it case jsonparser.String: return IRI(val) } return nil } func getAPLangRefField(data []byte, prop string) LangRef { val, err := jsonparser.GetString(data, prop) if err != nil { return LangRef("") } return LangRef(val) } // UnmarshalJSON tries to detect the type of the object in the json data and then outputs a matching // ActivityStreams object, if possible func UnmarshalJSON(data []byte) (Item, error) { return unmarshalToAPObject(data), nil } /* func unmarshal(data []byte, a interface{}) (interface{}, error) { ta := make(mockObj, 0) err := jsonld.Unmarshal(data, &ta) if err != nil { return nil, err } typ := reflect.TypeOf(a) val := reflect.ValueOf(a) if typ.Kind() == reflect.Ptr { typ = typ.Elem() val = val.Elem() } for i := 0; i < typ.NumField(); i++ { cField := typ.Field(i) cValue := val.Field(i) cTag := cField.Tag tag, _ := jsonld.LoadTag(cTag) var vv reflect.Value for key, j := range ta { if j == nil { continue } if key == tag.Name { if cField.Type.Implements(textUnmarshalerType) { m, _ := cValue.Interface().(encoding.TextUnmarshaler) m.UnmarshalText(j) vv = reflect.ValueOf(m) } if cField.Type.Implements(unmarshalerType) { m, _ := cValue.Interface().(json.Unmarshaler) m.UnmarshalJSON(j) vv = reflect.ValueOf(m) } if cField.Type.Implements(apUnmarshalerType) { o := getAPObjectByType(getType(j)) if o != nil { jsonld.Unmarshal([]byte(j), o) vv = reflect.ValueOf(o) } } } if vv.CanAddr() { cValue.Set(vv) fmt.Printf("\n\nReflected %q %q => %#v\n\n%#v\n", cField.Name, cField.Type, vv, tag.Name) } } } return a, nil } */ func getAPObjectByType(typ ActivityVocabularyType) (Item, error) { var ret Item var err error switch typ { case ObjectType: ret = ObjectNew(typ) case LinkType: ret = &Link{} o := ret.(*Link) o.Type = typ case ActivityType: ret = &Activity{} o := ret.(*Activity) o.Type = typ case IntransitiveActivityType: ret = &IntransitiveActivity{} o := ret.(*IntransitiveActivity) o.Type = typ case ActorType: ret = &Actor{} o := ret.(*Actor) o.Type = typ case CollectionType: ret = &Collection{} o := ret.(*Collection) o.Type = typ case OrderedCollectionType: ret = &OrderedCollection{} o := ret.(*OrderedCollection) o.Type = typ case CollectionPageType: ret = &CollectionPage{} o := ret.(*CollectionPage) o.Type = typ case OrderedCollectionPageType: ret = &OrderedCollectionPage{} o := ret.(*OrderedCollectionPage) o.Type = typ case ArticleType: ret = ObjectNew(typ) case AudioType: ret = ObjectNew(typ) case DocumentType: ret = ObjectNew(typ) case EventType: o := Object{} o.Type = typ case ImageType: ret = ObjectNew(typ) o := ret.(*Object) o.Type = typ case NoteType: ret = ObjectNew(typ) case PageType: ret = ObjectNew(typ) case PlaceType: ret = ObjectNew(typ) case ProfileType: ret = ObjectNew(typ) case RelationshipType: ret = ObjectNew(typ) case TombstoneType: ret = ObjectNew(typ) case VideoType: ret = ObjectNew(typ) case MentionType: ret = &Mention{} o := ret.(*Mention) o.Type = typ case ApplicationType: ret = &Application{} o := ret.(*Application) o.Type = typ case GroupType: ret = &Group{} o := ret.(*Group) o.Type = typ case OrganizationType: ret = &Organization{} o := ret.(*Organization) o.Type = typ case PersonType: ret = &Person{} o := ret.(*Person) o.Type = typ case ServiceType: ret = &Service{} o := ret.(*Service) o.Type = typ case AcceptType: ret = &Accept{} o := ret.(*Accept) o.Type = typ case AddType: ret = &Add{} o := ret.(*Add) o.Type = typ case AnnounceType: ret = &Announce{} o := ret.(*Announce) o.Type = typ case ArriveType: ret = &Arrive{} o := ret.(*Arrive) o.Type = typ case BlockType: ret = &Block{} o := ret.(*Block) o.Type = typ case CreateType: ret = &Create{} o := ret.(*Create) o.Type = typ case DeleteType: ret = &Delete{} o := ret.(*Delete) o.Type = typ case DislikeType: ret = &Dislike{} o := ret.(*Dislike) o.Type = typ case FlagType: ret = &Flag{} o := ret.(*Flag) o.Type = typ case FollowType: ret = &Follow{} o := ret.(*Follow) o.Type = typ case IgnoreType: ret = &Ignore{} o := ret.(*Ignore) o.Type = typ case InviteType: ret = &Invite{} o := ret.(*Invite) o.Type = typ case JoinType: ret = &Join{} o := ret.(*Join) o.Type = typ case LeaveType: ret = &Leave{} o := ret.(*Leave) o.Type = typ case LikeType: ret = &Like{} o := ret.(*Like) o.Type = typ case ListenType: ret = &Listen{} o := ret.(*Listen) o.Type = typ case MoveType: ret = &Move{} o := ret.(*Move) o.Type = typ case OfferType: ret = &Offer{} o := ret.(*Offer) o.Type = typ case QuestionType: ret = &Question{} o := ret.(*Question) o.Type = typ case RejectType: ret = &Reject{} o := ret.(*Reject) o.Type = typ case ReadType: ret = &Read{} o := ret.(*Read) o.Type = typ case RemoveType: ret = &Remove{} o := ret.(*Remove) o.Type = typ case TentativeRejectType: ret = &TentativeReject{} o := ret.(*TentativeReject) o.Type = typ case TentativeAcceptType: ret = &TentativeAccept{} o := ret.(*TentativeAccept) o.Type = typ case TravelType: ret = &Travel{} o := ret.(*Travel) o.Type = typ case UndoType: ret = &Undo{} o := ret.(*Undo) o.Type = typ case UpdateType: ret = &Update{} o := ret.(*Update) o.Type = typ case ViewType: ret = &View{} o := ret.(*View) o.Type = typ case "": // when no type is available use a plain Object ret = &Object{} default: ret = nil err = fmt.Errorf("unrecognized ActivityPub type %q", typ) } return ret, err }
-
-
activitystreams/unmarshalling_test.go (deleted)
-
@@ -1,14 +0,0 @@package activitystreams import "testing" func TestUnmarshalJSON(t *testing.T) { dataEmpty := []byte("{}") i, err := UnmarshalJSON(dataEmpty) if err != nil { t.Errorf("invalid unmarshalling %s", err) } o := *i.(*Object) validateEmptyObject(o, t) }
-
-
activitystreams/uri.go (deleted)
-
@@ -1,46 +0,0 @@package activitystreams import ( "strings" ) type ( // IRI is a Internationalized Resource Identifiers (IRIs) RFC3987 IRI string ) // String returns the String value of the IRI object func (i IRI) String() string { return string(i) } // GetLink func (i IRI) GetLink() IRI { return i } // UnmarshalJSON func (i *IRI) UnmarshalJSON(s []byte) error { *i = IRI(strings.Trim(string(s), "\"")) return nil } // IsObject func (i IRI) GetID() *ObjectID { return nil } // GetType func (i IRI) GetType() ActivityVocabularyType { return LinkType } // IsLink func (i IRI) IsLink() bool { return true } // IsObject func (i IRI) IsObject() bool { return false }
-
-
activitystreams/uri_test.go (deleted)
-
@@ -1,39 +0,0 @@package activitystreams import "testing" func TestIRI_GetLink(t *testing.T) { val := "http://example.com" u := IRI(val) if u.GetLink() != IRI(val) { t.Errorf("IRI %q should equal %q", u, val) } } func TestIRI_String(t *testing.T) { val := "http://example.com" u := IRI(val) if u.String() != val { t.Errorf("IRI %q should equal %q", u, val) } } func TestIRI_GetID(t *testing.T) { } func TestIRI_GetType(t *testing.T) { } func TestIRI_IsLink(t *testing.T) { } func TestIRI_IsObject(t *testing.T) { } func TestIRI_UnmarshalJSON(t *testing.T) { }
-
-
-
@@ -1,6 +1,6 @@package activitypub import as "github.com/go-ap/activitypub.go/activitystreams" import as "github.com/go-ap/activitystreams" // Actor is the ActivityPub version of an Activity Streams vocabulary Actor type Actor struct {
-
-
-
@@ -7,7 +7,7 @@ import ("net/http" "net/url" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) type RequestSignFn func(*http.Request) error
-
-
-
@@ -4,7 +4,7 @@ import ("strings" "testing" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) func TestNewClient(t *testing.T) {
-
-
-
@@ -3,7 +3,7 @@ package activitypubimport ( "time" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) // CreateActivity is the type for a create activity message
-
-
-
@@ -5,7 +5,7 @@ import ("testing" "time" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) func TestCreateActivityNew(t *testing.T) {
-
-
-
@@ -2,7 +2,7 @@ package activitypubimport ( "fmt" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) type (
-
-
-
@@ -2,7 +2,7 @@ package activitypubimport ( "fmt" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) type (
-
-
-
@@ -1,3 +1,7 @@module github.com/go-ap/activitypub.go module github.com/go-ap/activitypub require github.com/buger/jsonparser v0.0.0-20181023193515-52c6e1462ebd require ( github.com/buger/jsonparser v0.0.0-20181023193515-52c6e1462ebd github.com/go-ap/activitystreams v0.0.0-20190122151949-ac1e941c8736 github.com/go-ap/jsonld v0.0.0-20190122152743-fe4e38313f3a )
-
-
-
@@ -3,7 +3,7 @@ package activitypubimport ( "fmt" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) type (
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "reflect" "testing" )
-
-
jsonld/context.go (deleted)
-
@@ -1,216 +0,0 @@package jsonld import ( "encoding/json" "strings" ) // From the JSON-LD spec 3.3 // https://www.w3.org/TR/json-ld/#dfn-keyword const ( // @context // Used to define the short-hand names that are used throughout a JSON-LD document. // These short-hand names are called terms and help developers to express specific identifiers in a compact manner. // The @context keyword is described in detail in section 5.1 The Context. ContextKw Term = "@context" // @id //Used to uniquely identify things that are being described in the document with IRIs or blank node identifiers. // This keyword is described in section 5.3 Node Identifiers. IdKw Term = "@id" // @value // Used to specify the data that is associated with a particular property in the graph. // This keyword is described in section 6.9 String Internationalization and section 6.4 Typed Values. ValueKw Term = "@value" // @language // Used to specify the language for a particular string value or the default language of a JSON-LD document. // This keyword is described in section 6.9 String Internationalization. LanguageKw Term = "@language" //@type //Used to set the data type of a node or typed value. This keyword is described in section 6.4 Typed Values. TypeKw Term = "@type" // @container // Used to set the default container type for a term. This keyword is described in section 6.11 Sets and Lists. ContainerKw Term = "@container" //@list //Used to express an ordered set of data. This keyword is described in section 6.11 Sets and Lists. ListKw Term = "@list" // @set // Used to express an unordered set of data and to ensure that values are always represented as arrays. // This keyword is described in section 6.11 Sets and Lists. SetKw Term = "@set" // @reverse // Used to express reverse properties. This keyword is described in section 6.12 Reverse Properties. ReverseKw Term = "@reverse" // @index // Used to specify that a container is used to index information and that processing should continue deeper // into a JSON data structure. This keyword is described in section 6.16 Data Indexing. IndexKw Term = "@index" // @base // Used to set the base IRI against which relative IRIs are resolved. T // his keyword is described in section 6.1 Base IRI. BaseKw Term = "@base" // @vocab // Used to expand properties and values in @type with a common prefix IRI. // This keyword is described in section 6.2 Default Vocabulary. VocabKw Term = "@vocab" // @graph // Used to express a graph. This keyword is described in section 6.13 Named Graphs. GraphKw Term = "@graph" ) type ( // Ref basic type LangRef string // Term represents the JSON-LD term for @context maps Term string // IRI is a International Resource Identificator IRI string // Terms is an array of Term values Terms []Term ) // Nillable type Nillable interface { IsNil() bool } type IRILike interface { IsCompact() bool IsAbsolute() bool IsRelative() bool } func (i IRI) IsCompact() bool { return !i.IsAbsolute() && strings.Contains(string(i), ":") } func (i IRI) IsAbsolute() bool { return strings.Contains(string(i), "https://") } func (i IRI) IsRelative() bool { return !i.IsAbsolute() } var keywords = Terms{ BaseKw, ContextKw, ContainerKw, GraphKw, IdKw, IndexKw, LanguageKw, ListKw, ReverseKw, SetKw, TypeKw, ValueKw, VocabKw, } const NilTerm Term = "-" const NilLangRef LangRef = "-" type ContextObject struct { ID interface{} `jsonld:"@id,omitempty,collapsible"` Type interface{} `jsonld:"@type,omitempty,collapsible"` } // Context is of of the basic JSON-LD elements. // It represents an array of ContextElements type Context []ContextElement // ContextElement is used to map terms to IRIs or JSON objects. // Terms are case sensitive and any valid string that is not a reserved JSON-LD // keyword can be used as a term. type ContextElement struct { Term Term IRI IRI } func GetContext() Context { return Context{} } //type Context Collapsible // Collapsible is an interface used by the JSON-LD marshaller to collapse a struct to one single value type Collapsible interface { Collapse() interface{} } // Collapse returns the plain text collapsed value of the current Context object func (c Context) Collapse() interface{} { if len(c) == 1 && len(c[0].IRI) > 0 { return c[0].IRI } for _, el := range c { if el.Term == NilTerm { } } return c } // Collapse returns the plain text collapsed value of the current IRI string func (i IRI) Collapse() interface{} { return i } // MarshalText basic stringify function func (i IRI) MarshalText() ([]byte, error) { return []byte(i), nil } // MarshalJSON returns the JSON document represented by the current Context // This should return : // If only one element in the context and the element has no Term -> json marshaled string // If multiple elements in the context without Term -> json marshaled array of strings // If multiple elements where at least one doesn't have a Term and one has a Term -> json marshaled array // If multiple elements where all have Terms -> json marshaled object func (c Context) MarshalJSON() ([]byte, error) { mapIRI := make(map[Term]IRI, 0) arr := make([]interface{}, 0) i := 0 if len(c) == 1 && len(c[0].IRI) > 0 { return json.Marshal(c[0].IRI) } for _, el := range c { t := el.Term iri := el.IRI if t.IsNil() { arr = append(arr, iri) i += 1 } else { if len(iri) > 0 { mapIRI[t] = iri } } } if len(mapIRI) > 0 { if len(arr) == 0 { return json.Marshal(mapIRI) } arr = append(arr, mapIRI) } return json.Marshal(arr) } // UnmarshalJSON tries to load the Context from the incoming json value func (c *Context) UnmarshalJSON(data []byte) error { return nil } // IsNil returns if current LangRef is equal to empty string or to its nil value func (l LangRef) IsNil() bool { return len(l) == 0 || l == NilLangRef } // IsNil returns if current IRI is equal to empty string func (i IRI) IsNil() bool { return len(i) == 0 } // IsNil returns if current Term is equal to empty string or to its nil value func (i Term) IsNil() bool { return len(i) == 0 || i == NilTerm }
-
-
jsonld/context_test.go (deleted)
-
@@ -1,101 +0,0 @@package jsonld import ( "bytes" "encoding/json" "strings" "testing" ) func TestRef_MarshalText(t *testing.T) { test := "test" a := IRI(test) out, err := a.MarshalText() if err != nil { t.Errorf("Error %s", err) } if bytes.Compare(out, []byte(test)) != 0 { t.Errorf("Invalid result '%s', expected '%s'", out, test) } } func TestContext_MarshalJSON(t *testing.T) { { url := "test" c := Context{{NilTerm, IRI(url)}} out, err := c.MarshalJSON() if err != nil { t.Errorf("%s", err) } if !strings.Contains(string(out), url) { t.Errorf("Json doesn't contain %s, %s", url, string(out)) } jUrl, _ := json.Marshal(url) if !bytes.Equal(jUrl, out) { t.Errorf("Strings should be equal %s, %s", jUrl, out) } } { url := "example.com" asTerm := "testingTerm##" asUrl := "https://activitipubrocks.com" c2 := Context{{NilTerm, IRI(url)}, {Term(asTerm), IRI(asUrl)}} out, err := c2.MarshalJSON() if err != nil { t.Errorf("%s", err) } if !strings.Contains(string(out), url) { t.Errorf("Json doesn't contain URL %s, %s", url, string(out)) } if !strings.Contains(string(out), asUrl) { t.Errorf("Json doesn't contain URL %s, %s", asUrl, string(out)) } if !strings.Contains(string(out), asTerm) { t.Errorf("Json doesn't contain Term %s, %s", asTerm, string(out)) } } { url := "test" testTerm := "test_term" asTerm := "testingTerm##" asUrl := "https://activitipubrocks.com" c3 := Context{{Term(testTerm), IRI(url)}, {Term(asTerm), IRI(asUrl)}} out, err := c3.MarshalJSON() if err != nil { t.Errorf("%s", err) } if !strings.Contains(string(out), url) { t.Errorf("Json doesn't contain URL %s, %s", url, string(out)) } if !strings.Contains(string(out), asUrl) { t.Errorf("Json doesn't contain URL %s, %s", asUrl, string(out)) } if !strings.Contains(string(out), asTerm) { t.Errorf("Json doesn't contain Term %s, %s", asTerm, string(out)) } if !strings.Contains(string(out), testTerm) { t.Errorf("Json doesn't contain Term %s, %s", testTerm, string(out)) } } { url1 := "test" url2 := "http://example.com" c := Context{ {IRI: IRI(url1)}, {IRI: IRI(url2)}, } out, err := c.MarshalJSON() if err != nil { t.Errorf("%s", err) } if !strings.Contains(string(out), url1) { t.Errorf("Json doesn't contain %s, %s", url1, string(out)) } if !strings.Contains(string(out), url2) { t.Errorf("Json doesn't contain %s, %s", url1, string(out)) } } }
-
-
jsonld/decode.go (deleted)
-
@@ -1,1253 +0,0 @@package jsonld import ( "bytes" "encoding" "encoding/base64" "encoding/json" "errors" "fmt" "reflect" "runtime" "strconv" "unicode" "unicode/utf16" "unicode/utf8" ) // Unmarshal parses the JSON-encoded data and stores the result // in the value pointed to by v. If v is nil or not a pointer, // Unmarshal returns an InvalidUnmarshalError. // // Unmarshal uses the inverse of the encodings that // Marshal uses, allocating maps, slices, and pointers as necessary, // with the following additional rules: // // To unmarshal JSON into a pointer, Unmarshal first handles the case of // the JSON being the JSON literal null. In that case, Unmarshal sets // the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into // the value pointed at by the pointer. If the pointer is nil, Unmarshal // allocates a new value for it to point to. // // To unmarshal JSON into a value implementing the Unmarshaler interface, // Unmarshal calls that value's UnmarshalJSON method, including // when the input is a JSON null. // Otherwise, if the value implements encoding.TextUnmarshaler // and the input is a JSON quoted string, Unmarshal calls that value's // UnmarshalText method with the unquoted form of the string. // // To unmarshal JSON into a struct, Unmarshal matches incoming object // keys to the keys used by Marshal (either the struct field name or its tag), // preferring an exact match but also accepting a case-insensitive match. // Unmarshal will only set exported fields of the struct. // // To unmarshal JSON into an interface value, // Unmarshal stores one of these in the interface value: // // bool, for JSON booleans // float64, for JSON numbers // string, for JSON strings // []interface{}, for JSON arrays // map[string]interface{}, for JSON objects // nil for JSON null // // To unmarshal a JSON array into a slice, Unmarshal resets the slice length // to zero and then appends each element to the slice. // As a special case, to unmarshal an empty JSON array into a slice, // Unmarshal replaces the slice with a new empty slice. // // To unmarshal a JSON array into a Go array, Unmarshal decodes // JSON array elements into corresponding Go array elements. // If the Go array is smaller than the JSON array, // the additional JSON array elements are discarded. // If the JSON array is smaller than the Go array, // the additional Go array elements are set to zero values. // // To unmarshal a JSON object into a map, Unmarshal first establishes a map to // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal // reuses the existing map, keeping existing entries. Unmarshal then stores // key-value pairs from the JSON object into the map. The map's key type must // either be a string, an integer, or implement encoding.TextUnmarshaler. // // If a JSON value is not appropriate for a given target type, // or if a JSON number overflows the target type, Unmarshal // skips that field and completes the unmarshaling as best it can. // If no more serious errors are encountered, Unmarshal returns // an UnmarshalTypeError describing the earliest such error. In any // case, it's not guaranteed that all the remaining fields following // the problematic one will be unmarshaled into the target object. // // The JSON null value unmarshals into an interface, map, pointer, or slice // by setting that Go value to nil. Because null is often used in JSON to mean // ``not present,'' unmarshaling a JSON null into any other Go type has no effect // on the value and produces no error. // // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement // character U+FFFD. // func Unmarshal(data []byte, v interface{}) error { var d decodeState err := checkValid(data, &d.scan) if err != nil { return err } d.init(data) return d.unmarshal(&v) } // An UnmarshalTypeError describes a JSON value that was // not appropriate for a value of a specific Go type. type UnmarshalTypeError struct { Value string // description of JSON value - "bool", "array", "number -5" Type reflect.Type // type of Go value it could not be assigned to Offset int64 // error occurred after reading Offset bytes Struct string // name of the struct type containing the field Field string // name of the field holding the Go value } func (e *UnmarshalTypeError) Error() string { if e.Struct != "" || e.Field != "" { return tagLabel + ": cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() } return tagLabel + ": cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() } // An UnmarshalFieldError describes a JSON object key that // led to an unexported (and therefore unwritable) struct field. // (No longer used; kept for compatibility.) type UnmarshalFieldError struct { Key string Type reflect.Type Field reflect.StructField } func (e *UnmarshalFieldError) Error() string { return tagLabel + ": cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() } // An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. // (The argument to Unmarshal must be a non-nil pointer.) type InvalidUnmarshalError struct { Type reflect.Type } func (e *InvalidUnmarshalError) Error() string { if e.Type == nil { return tagLabel + ": Unmarshal(nil)" } if e.Type.Kind() != reflect.Ptr { return tagLabel + ": Unmarshal(non-pointer " + e.Type.String() + ")" } return tagLabel + ": Unmarshal(nil " + e.Type.String() + ")" } func (d *decodeState) unmarshal(v interface{}) (err error) { defer func() { if r := recover(); r != nil { if _, ok := r.(runtime.Error); ok { panic(r) } err = r.(error) } }() rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { return &InvalidUnmarshalError{reflect.TypeOf(v)} } d.scan.reset() // We decode rv not rv.Elem because the Unmarshaler interface // test must be applied at the top level of the value. d.value(rv) return d.savedError } // A Number represents a JSON number literal. type Number string // String returns the literal text of the number. func (n Number) String() string { return string(n) } // Float64 returns the number as a float64. func (n Number) Float64() (float64, error) { return strconv.ParseFloat(string(n), 64) } // Int64 returns the number as an int64. func (n Number) Int64() (int64, error) { return strconv.ParseInt(string(n), 10, 64) } // isValidNumber reports whether s is a valid JSON number literal. func isValidNumber(s string) bool { // This function implements the JSON numbers grammar. // See https://tools.ietf.org/html/rfc7159#section-6 // and http://json.org/number.gif if s == "" { return false } // Optional - if s[0] == '-' { s = s[1:] if s == "" { return false } } // Digits switch { default: return false case s[0] == '0': s = s[1:] case '1' <= s[0] && s[0] <= '9': s = s[1:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] } } // . followed by 1 or more digits. if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { s = s[2:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] } } // e or E followed by an optional - or + and // 1 or more digits. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { s = s[1:] if s[0] == '+' || s[0] == '-' { s = s[1:] if s == "" { return false } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] } } // Make sure we are at the end. return s == "" } // decodeState represents the state while decoding a JSON value. type decodeState struct { data []byte off int // read offset in data scan scanner nextscan scanner // for calls to nextValue errorContext struct { // provides context for type errors Struct string Field string } savedError error useNumber bool } // errPhase is used for errors that should not happen unless // there is a bug in the JSON decoder or something is editing // the data slice while the decoder executes. var errPhase = errors.New(tagLabel + " decoder out of sync - data changing underfoot?") func (d *decodeState) init(data []byte) *decodeState { d.data = data d.off = 0 d.savedError = nil d.errorContext.Struct = "" d.errorContext.Field = "" return d } // error aborts the decoding by panicking with err. func (d *decodeState) error(err error) { panic(d.addErrorContext(err)) } // saveError saves the first err it is called with, // for reporting at the end of the unmarshal. func (d *decodeState) saveError(err error) { if d.savedError == nil { d.savedError = d.addErrorContext(err) } } // addErrorContext returns a new error enhanced with information from d.errorContext func (d *decodeState) addErrorContext(err error) error { if d.errorContext.Struct != "" || d.errorContext.Field != "" { switch err := err.(type) { case *UnmarshalTypeError: err.Struct = d.errorContext.Struct err.Field = d.errorContext.Field return err } } return err } // next cuts off and returns the next full JSON value in d.data[d.off:]. // The next value is known to be an object or array, not a literal. func (d *decodeState) next() []byte { c := d.data[d.off] item, rest, err := nextValue(d.data[d.off:], &d.nextscan) if err != nil { d.error(err) } d.off = len(d.data) - len(rest) // Our scanner has seen the opening brace/bracket // and thinks we're still in the middle of the object. // invent a closing brace/bracket to get it out. if c == '{' { d.scan.step(&d.scan, '}') } else { d.scan.step(&d.scan, ']') } return item } // scanWhile processes bytes in d.data[d.off:] until it // receives a scan code not equal to op. // It updates d.off and returns the new scan code. func (d *decodeState) scanWhile(op int) int { var newOp int for { if d.off >= len(d.data) { newOp = d.scan.eof() d.off = len(d.data) + 1 // mark processed EOF with len+1 } else { c := d.data[d.off] d.off++ newOp = d.scan.step(&d.scan, c) } if newOp != op { break } } return newOp } // value decodes a JSON value from d.data[d.off:] into the value. // it updates d.off to point past the decoded value. func (d *decodeState) value(v reflect.Value) { if !v.IsValid() { _, rest, err := nextValue(d.data[d.off:], &d.nextscan) if err != nil { d.error(err) } d.off = len(d.data) - len(rest) // d.scan thinks we're still at the beginning of the item. // Feed in an empty string - the shortest, simplest value - // so that it knows we got to the end of the value. if d.scan.redo { // rewind. d.scan.redo = false d.scan.step = stateBeginValue } d.scan.step(&d.scan, '"') d.scan.step(&d.scan, '"') n := len(d.scan.parseState) if n > 0 && d.scan.parseState[n-1] == parseObjectKey { // d.scan thinks we just read an object key; finish the object d.scan.step(&d.scan, ':') d.scan.step(&d.scan, '"') d.scan.step(&d.scan, '"') d.scan.step(&d.scan, '}') } return } switch op := d.scanWhile(scanSkipSpace); op { default: d.error(errPhase) case scanBeginArray: d.array(v) case scanBeginObject: d.object(v) case scanBeginLiteral: d.literal(v) } } type unquotedValue struct{} // valueQuoted is like value but decodes a // quoted string literal or literal null into an interface value. // If it finds anything other than a quoted string literal or null, // valueQuoted returns unquotedValue{}. func (d *decodeState) valueQuoted() interface{} { switch op := d.scanWhile(scanSkipSpace); op { default: d.error(errPhase) case scanBeginArray: d.array(reflect.Value{}) case scanBeginObject: d.object(reflect.Value{}) case scanBeginLiteral: switch v := d.literalInterface().(type) { case nil, string: return v } } return unquotedValue{} } // indirect walks down v allocating pointers as needed, // until it gets to a non-pointer. // if it encounters an Unmarshaler, indirect stops and returns that. // if decodingNull is true, indirect stops at the last pointer so it can be set to nil. func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (json.Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { // If v is a named type and is addressable, // start with its address, so that if the type has pointer methods, // we find them. if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { v = v.Addr() } for { // Load value from interface, but only if the result will be // usefully addressable. if v.Kind() == reflect.Interface && !v.IsNil() { e := v.Elem() if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { v = e continue } } if v.Kind() != reflect.Ptr { break } if v.Elem().Kind() != reflect.Ptr && decodingNull && v.CanSet() { break } if v.IsNil() { v.Set(reflect.New(v.Type().Elem())) } if v.Type().NumMethod() > 0 { if u, ok := v.Interface().(json.Unmarshaler); ok { return u, nil, reflect.Value{} } if !decodingNull { if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { return nil, u, reflect.Value{} } } } v = v.Elem() } return nil, nil, v } // array consumes an array from d.data[d.off-1:], decoding into the value v. // the first byte of the array ('[') has been read already. func (d *decodeState) array(v reflect.Value) { // Check for unmarshaler. u, ut, pv := d.indirect(v, false) if u != nil { d.off-- err := u.UnmarshalJSON(d.next()) if err != nil { d.error(err) } return } if ut != nil { d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) d.off-- d.next() return } v = pv // Check type of target. switch v.Kind() { case reflect.Interface: if v.NumMethod() == 0 { // Decoding into nil interface? Switch to non-reflect code. v.Set(reflect.ValueOf(d.arrayInterface())) return } // Otherwise it's invalid. fallthrough default: d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) d.off-- d.next() return case reflect.Array: case reflect.Slice: break } i := 0 for { // Look ahead for ] - can only happen on first iteration. op := d.scanWhile(scanSkipSpace) if op == scanEndArray { break } // Back up so d.value can have the byte we just read. d.off-- d.scan.undo(op) // Get element of array, growing if necessary. if v.Kind() == reflect.Slice { // Grow slice if necessary if i >= v.Cap() { newcap := v.Cap() + v.Cap()/2 if newcap < 4 { newcap = 4 } newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) reflect.Copy(newv, v) v.Set(newv) } if i >= v.Len() { v.SetLen(i + 1) } } if i < v.Len() { // Decode into element. d.value(v.Index(i)) } else { // Ran out of fixed array: skip. d.value(reflect.Value{}) } i++ // Next token must be , or ]. op = d.scanWhile(scanSkipSpace) if op == scanEndArray { break } if op != scanArrayValue { d.error(errPhase) } } if i < v.Len() { if v.Kind() == reflect.Array { // Array. Zero the rest. z := reflect.Zero(v.Type().Elem()) for ; i < v.Len(); i++ { v.Index(i).Set(z) } } else { v.SetLen(i) } } if i == 0 && v.Kind() == reflect.Slice { v.Set(reflect.MakeSlice(v.Type(), 0, 0)) } } var nullLiteral = []byte("null") var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() // object consumes an object from d.data[d.off-1:], decoding into the value v. // the first byte ('{') of the object has been read already. func (d *decodeState) object(v reflect.Value) { // Check for unmarshaler. u, ut, pv := d.indirect(v, false) if u != nil { d.off-- err := u.UnmarshalJSON(d.next()) if err != nil { d.error(err) } return } if ut != nil { d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) d.off-- d.next() // skip over { } in input return } v = pv // Decoding into nil interface? Switch to non-reflect code. if v.Kind() == reflect.Interface && v.NumMethod() == 0 { v.Set(reflect.ValueOf(d.objectInterface())) return } // Check type of target: // struct or // map[T1]T2 where T1 is string, an integer type, // or an encoding.TextUnmarshaler switch v.Kind() { case reflect.Map: // Map key must either have string kind, have an integer kind, // or be an encoding.TextUnmarshaler. t := v.Type() switch t.Key().Kind() { case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: default: if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) { d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) d.off-- d.next() // skip over { } in input return } } if v.IsNil() { v.Set(reflect.MakeMap(t)) } case reflect.Struct: // ok default: d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) d.off-- d.next() // skip over { } in input return } var mapElem reflect.Value for { // Read opening " of string key or closing }. op := d.scanWhile(scanSkipSpace) if op == scanEndObject { // closing } - can only happen on first iteration. break } if op != scanBeginLiteral { d.error(errPhase) } // Read key. start := d.off - 1 op = d.scanWhile(scanContinue) item := d.data[start : d.off-1] key, ok := unquoteBytes(item) if !ok { d.error(errPhase) } // Figure out field corresponding to key. var subv reflect.Value destring := false // whether the value is wrapped in a string to be decoded first if v.Kind() == reflect.Map { elemType := v.Type().Elem() if !mapElem.IsValid() { mapElem = reflect.New(elemType).Elem() } else { mapElem.Set(reflect.Zero(elemType)) } subv = mapElem } else { var f *field fields := cachedTypeFields(v.Type()) for i := range fields { ff := &fields[i] if bytes.Equal(ff.nameBytes, key) { f = ff break } if f == nil && ff.equalFold(ff.nameBytes, key) { f = ff } } if f != nil { subv = v destring = f.quoted for _, i := range f.index { if subv.Kind() == reflect.Ptr { if subv.IsNil() { subv.Set(reflect.New(subv.Type().Elem())) } subv = subv.Elem() } subv = subv.Field(i) } d.errorContext.Field = f.name d.errorContext.Struct = v.Type().Name() } } // Read : before value. if op == scanSkipSpace { op = d.scanWhile(scanSkipSpace) } if op != scanObjectKey { d.error(errPhase) } if destring { switch qv := d.valueQuoted().(type) { case nil: d.literalStore(nullLiteral, subv, false) case string: d.literalStore([]byte(qv), subv, true) default: d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) } } else { d.value(subv) } // Write value back to map; // if using struct, subv points into struct already. if v.Kind() == reflect.Map { kt := v.Type().Key() var kv reflect.Value switch { case kt.Kind() == reflect.String: kv = reflect.ValueOf(key).Convert(kt) case reflect.PtrTo(kt).Implements(textUnmarshalerType): kv = reflect.New(v.Type().Key()) d.literalStore(item, kv, true) kv = kv.Elem() default: switch kt.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: s := string(key) n, err := strconv.ParseInt(s, 10, 64) if err != nil || reflect.Zero(kt).OverflowInt(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) return } kv = reflect.ValueOf(n).Convert(kt) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: s := string(key) n, err := strconv.ParseUint(s, 10, 64) if err != nil || reflect.Zero(kt).OverflowUint(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) return } kv = reflect.ValueOf(n).Convert(kt) default: panic(tagLabel + ": Unexpected key type") // should never occur } } v.SetMapIndex(kv, subv) } // Next token must be , or }. op = d.scanWhile(scanSkipSpace) if op == scanEndObject { break } if op != scanObjectValue { d.error(errPhase) } d.errorContext.Struct = "" d.errorContext.Field = "" } } // literal consumes a literal from d.data[d.off-1:], decoding into the value v. // The first byte of the literal has been read already // (that's how the caller knows it's a literal). func (d *decodeState) literal(v reflect.Value) { // All bytes inside literal return scanContinue op code. start := d.off - 1 op := d.scanWhile(scanContinue) // Scan read one byte too far; back up. d.off-- d.scan.undo(op) d.literalStore(d.data[start:d.off], v, false) } // convertNumber converts the number literal s to a float64 or a Number // depending on the setting of d.useNumber. func (d *decodeState) convertNumber(s string) (interface{}, error) { if d.useNumber { return Number(s), nil } f, err := strconv.ParseFloat(s, 64) if err != nil { return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)} } return f, nil } var numberType = reflect.TypeOf(Number("")) // literalStore decodes a literal stored in item into v. // // fromQuoted indicates whether this literal came from unwrapping a // string from the ",string" struct tag option. this is used only to // produce more helpful error messages. func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { // Check for unmarshaler. if len(item) == 0 { //Empty string given d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) return } isNull := item[0] == 'n' // null u, ut, pv := d.indirect(v, isNull) if u != nil { err := u.UnmarshalJSON(item) if err != nil { d.error(err) } return } if ut != nil { if item[0] != '"' { if fromQuoted { d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { var val string switch item[0] { case 'n': val = "null" case 't', 'f': val = "bool" default: val = "number" } d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)}) } return } s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } err := ut.UnmarshalText(s) if err != nil { d.error(err) } return } v = pv switch c := item[0]; c { case 'n': // null // The main parser checks that only true and false can reach here, // but if this was a quoted string input, it could be anything. if fromQuoted && string(item) != "null" { d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) break } switch v.Kind() { case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: v.Set(reflect.Zero(v.Type())) // otherwise, ignore null for primitives/string } case 't', 'f': // true, false value := item[0] == 't' // The main parser checks that only true and false can reach here, // but if this was a quoted string input, it could be anything. if fromQuoted && string(item) != "true" && string(item) != "false" { d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) break } switch v.Kind() { default: if fromQuoted { d.saveError(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) } case reflect.Bool: v.SetBool(value) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(value)) } else { d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) } } case '"': // string s, ok := unquoteBytes(item) if !ok { if fromQuoted { d.error(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } switch v.Kind() { default: d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) case reflect.Slice: if v.Type().Elem().Kind() != reflect.Uint8 { d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) break } b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) n, err := base64.StdEncoding.Decode(b, s) if err != nil { d.saveError(err) break } v.SetBytes(b[:n]) case reflect.String: v.SetString(string(s)) case reflect.Interface: if v.NumMethod() == 0 { v.Set(reflect.ValueOf(string(s))) } else { d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) } } default: // number if c != '-' && (c < '0' || c > '9') { if fromQuoted { d.error(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(errPhase) } } s := string(item) switch v.Kind() { default: if v.Kind() == reflect.String && v.Type() == numberType { v.SetString(s) if !isValidNumber(s) { d.error(fmt.Errorf(tagLabel+": invalid number literal, trying to unmarshal %q into Number", item)) } break } if fromQuoted { d.error(fmt.Errorf(tagLabel+": invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) } case reflect.Interface: n, err := d.convertNumber(s) if err != nil { d.saveError(err) break } if v.NumMethod() != 0 { d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) break } v.Set(reflect.ValueOf(n)) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetInt(n) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetUint(n) case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) break } v.SetFloat(n) } } } // The xxxInterface routines build up a value to be stored // in an empty interface. They are not strictly necessary, // but they avoid the weight of reflection in this common case. // valueInterface is like value but returns interface{} func (d *decodeState) valueInterface() interface{} { switch d.scanWhile(scanSkipSpace) { default: d.error(errPhase) panic("unreachable") case scanBeginArray: return d.arrayInterface() case scanBeginObject: return d.objectInterface() case scanBeginLiteral: return d.literalInterface() } } // arrayInterface is like array but returns []interface{}. func (d *decodeState) arrayInterface() []interface{} { var v = make([]interface{}, 0) for { // Look ahead for ] - can only happen on first iteration. op := d.scanWhile(scanSkipSpace) if op == scanEndArray { break } // Back up so d.value can have the byte we just read. d.off-- d.scan.undo(op) v = append(v, d.valueInterface()) // Next token must be , or ]. op = d.scanWhile(scanSkipSpace) if op == scanEndArray { break } if op != scanArrayValue { d.error(errPhase) } } return v } // objectInterface is like object but returns map[string]interface{}. func (d *decodeState) objectInterface() map[string]interface{} { m := make(map[string]interface{}) for { // Read opening " of string key or closing }. op := d.scanWhile(scanSkipSpace) if op == scanEndObject { // closing } - can only happen on first iteration. break } if op != scanBeginLiteral { d.error(errPhase) } // Read string key. start := d.off - 1 op = d.scanWhile(scanContinue) item := d.data[start : d.off-1] key, ok := unquote(item) if !ok { d.error(errPhase) } // Read : before value. if op == scanSkipSpace { op = d.scanWhile(scanSkipSpace) } if op != scanObjectKey { d.error(errPhase) } // Read value. m[key] = d.valueInterface() // Next token must be , or }. op = d.scanWhile(scanSkipSpace) if op == scanEndObject { break } if op != scanObjectValue { d.error(errPhase) } } return m } // literalInterface is like literal but returns an interface value. func (d *decodeState) literalInterface() interface{} { // All bytes inside literal return scanContinue op code. start := d.off - 1 op := d.scanWhile(scanContinue) // Scan read one byte too far; back up. d.off-- d.scan.undo(op) item := d.data[start:d.off] switch c := item[0]; c { case 'n': // null return nil case 't', 'f': // true, false return c == 't' case '"': // string s, ok := unquote(item) if !ok { d.error(errPhase) } return s default: // number if c != '-' && (c < '0' || c > '9') { d.error(errPhase) } n, err := d.convertNumber(string(item)) if err != nil { d.saveError(err) } return n } } // getu4 decodes \uXXXX from the beginning of s, returning the hex value, // or it returns -1. func getu4(s []byte) rune { if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { return -1 } r, err := strconv.ParseUint(string(s[2:6]), 16, 64) if err != nil { return -1 } return rune(r) } // unquote converts a quoted JSON string literal s into an actual string t. // The rules are different than for Go, so cannot use strconv.Unquote. func unquote(s []byte) (t string, ok bool) { s, ok = unquoteBytes(s) t = string(s) return } func unquoteBytes(s []byte) (t []byte, ok bool) { if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { return } s = s[1 : len(s)-1] // Check for unusual characters. If there are none, // then no unquoting is needed, so return a slice of the // original bytes. r := 0 for r < len(s) { c := s[r] if c == '\\' || c == '"' || c < ' ' { break } if c < utf8.RuneSelf { r++ continue } rr, size := utf8.DecodeRune(s[r:]) if rr == utf8.RuneError && size == 1 { break } r += size } if r == len(s) { return s, true } b := make([]byte, len(s)+2*utf8.UTFMax) w := copy(b, s[0:r]) for r < len(s) { // Out of room? Can only happen if s is full of // malformed UTF-8 and we're replacing each // byte with RuneError. if w >= len(b)-2*utf8.UTFMax { nb := make([]byte, (len(b)+utf8.UTFMax)*2) copy(nb, b[0:w]) b = nb } switch c := s[r]; { case c == '\\': r++ if r >= len(s) { return } switch s[r] { default: return case '"', '\\', '/', '\'': b[w] = s[r] r++ w++ case 'b': b[w] = '\b' r++ w++ case 'f': b[w] = '\f' r++ w++ case 'n': b[w] = '\n' r++ w++ case 'r': b[w] = '\r' r++ w++ case 't': b[w] = '\t' r++ w++ case 'u': r-- rr := getu4(s[r:]) if rr < 0 { return } r += 6 if utf16.IsSurrogate(rr) { rr1 := getu4(s[r:]) if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { // A valid pair; consume. r += 6 w += utf8.EncodeRune(b[w:], dec) break } // Invalid surrogate; fall back to replacement rune. rr = unicode.ReplacementChar } w += utf8.EncodeRune(b[w:], rr) } // Quote, control characters are invalid. case c == '"', c < ' ': return // ASCII case c < utf8.RuneSelf: b[w] = c r++ w++ // Coerce to well-formed UTF-8. default: rr, size := utf8.DecodeRune(s[r:]) r += size w += utf8.EncodeRune(b[w:], rr) } } return b[0:w], true }
-
-
jsonld/decode_test.go (deleted)
-
@@ -1,149 +0,0 @@package jsonld import ( "strconv" "testing" ) func TestUnmarshalWithEmptyJsonObject(t *testing.T) { obj := mockTypeA{} err := Unmarshal([]byte("{}"), &obj) if err != nil { t.Error(err) } if obj.Id != "" { t.Errorf("Id should have been an empty string, found %s", obj.Id) } if obj.Name != "" { t.Errorf("Name should have been an empty string, found %s", obj.Name) } if obj.Type != "" { t.Errorf("Type should have been an empty string, found %s", obj.Type) } if obj.PropA != "" { t.Errorf("PropA should have been an empty string, found %s", obj.PropA) } if obj.PropB != 0 { t.Errorf("PropB should have been 0.0, found %f", obj.PropB) } } type mockWithContext struct { mockTypeA Context Context `jsonld:"@context"` } func TestUnmarshalWithEmptyJsonObjectWithStringContext(t *testing.T) { obj := mockWithContext{} url := "http://www.habarnam.ro" data := []byte(`{"@context": "` + url + `" }`) err := Unmarshal(data, &obj) if err != nil { t.Error(err) } if obj.Id != "" { t.Errorf("Id should have been an empty string, found %s", obj.Id) } if obj.Name != "" { t.Errorf("Name should have been an empty string, found %s", obj.Name) } if obj.Type != "" { t.Errorf("Type should have been an empty string, found %s", obj.Type) } if obj.PropA != "" { t.Errorf("PropA should have been an empty string, found %s", obj.PropA) } if obj.PropB != 0 { t.Errorf("PropB should have been 0.0, found %f", obj.PropB) } } func TestUnmarshalWithEmptyJsonObjectWithObjectContext(t *testing.T) { obj := mockWithContext{} url := "http://www.habarnam.ro" data := []byte(`{"@context": { "@url": "` + url + `"} }`) err := Unmarshal(data, &obj) if err != nil { t.Error(err) } if obj.Id != "" { t.Errorf("Id should have been an empty string, found %s", obj.Id) } if obj.Name != "" { t.Errorf("Name should have been an empty string, found %s", obj.Name) } if obj.Type != "" { t.Errorf("Type should have been an empty string, found %s", obj.Type) } if obj.PropA != "" { t.Errorf("PropA should have been an empty string, found %s", obj.PropA) } if obj.PropB != 0 { t.Errorf("PropB should have been 0.0, found %f", obj.PropB) } } func TestUnmarshalWithEmptyJsonObjectWithOneLanguageContext(t *testing.T) { obj := mockWithContext{} url := "http://www.habarnam.ro" langEn := "en-US" data := []byte(`{"@context": { "@url": "` + url + `", "@language": "` + langEn + `"} }`) err := Unmarshal(data, &obj) if err != nil { t.Error(err) } if obj.Id != "" { t.Errorf("Id should have been an empty string, found %s", obj.Id) } if obj.Name != "" { t.Errorf("Name should have been an empty string, found %s", obj.Name) } if obj.Type != "" { t.Errorf("Type should have been an empty string, found %s", obj.Type) } if obj.PropA != "" { t.Errorf("PropA should have been an empty string, found %s", obj.PropA) } if obj.PropB != 0 { t.Errorf("PropB should have been 0.0, found %f", obj.PropB) } } func TestUnmarshalWithEmptyJsonObjectWithFullObject(t *testing.T) { obj := mockWithContext{} url := "http://www.habarnam.ro" langEn := "en-US" propA := "ana" var propB float32 = 6.66 typ := "test" name := "test object #1" id := "777sdad" data := []byte(`{ "@context": { "@url": "` + url + `", "@language": "` + langEn + `"}, "PropA": "` + propA + `", "PropB": ` + strconv.FormatFloat(float64(propB), 'f', 2, 32) + `, "Id" : "` + id + `", "Name" : "` + name + `", "Type" : "` + typ + `" }`) err := Unmarshal(data, &obj) if err != nil { t.Error(err) } if obj.Id != id { t.Errorf("Id should have been %q, found %q", id, obj.Id) } if obj.Name != name { t.Errorf("Name should have been %q, found %q", name, obj.Name) } if obj.Type != typ { t.Errorf("Type should have been %q, found %q", typ, obj.Type) } if obj.PropA != propA { t.Errorf("PropA should have been %q, found %q", propA, obj.PropA) } if obj.PropB != propB { t.Errorf("PropB should have been %f, found %f", propB, obj.PropB) } }
-
-
jsonld/encode.go (deleted)
-
@@ -1,1369 +0,0 @@// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package jsonld implements encoding and decoding of JSON as defined in // RFC 4627. The mapping between JSON and Go values is described // in the documentation for the Marshal and Unmarshal functions. // // See tagLabel + " and Go" for an introduction to this package: // https://golang.org/doc/articles/json_and_go.html package jsonld import ( "bytes" "encoding" "encoding/base64" "encoding/json" "fmt" "math" "reflect" "runtime" "sort" "strconv" "strings" "sync" "sync/atomic" "unicode" "unicode/utf8" ) var Ctxt Collapsible const ( tagLabel = "jsonld" tagOmitEmpty = "omitempty" tagCollapsible = "collapsible" ) type payloadWithContext struct { Context Collapsible `jsonld:"@context,omitempty,collapsible"` ID interface{} `jsonld:"@id,omitempty,collapsible"` Type interface{} `jsonld:"@type,omitempty,collapsible"` Obj interface{} } func (p payloadWithContext) Collapse() interface{} { return p } // WithContext func WithContext(c Collapsible) payloadWithContext { Ctxt = c return payloadWithContext{ Context: c, } } var payloadType = reflect.TypeOf(new(payloadWithContext)).Elem() // Marshal func (p payloadWithContext) Marshal(v interface{}) ([]byte, error) { p.Obj = v return Marshal(p) } // Tag used by structs from the ActivityPub package to Marshal and Unmarshal to/from JSON-LD type Tag struct { Name string Ignore bool OmitEmpty bool Collapsible bool } // LoadTag used by structs from the ActivityPub package to Marshal and Unmarshal to/from JSON-LD func LoadTag(tag reflect.StructTag) (Tag, bool) { jlTag, ok := tag.Lookup(tagLabel) if !ok { return Tag{}, false } val := strings.Split(jlTag, ",") cont := func(arr []string, s string) bool { for _, v := range arr { if v == s { return true } } return false } t := Tag{ OmitEmpty: cont(val, tagOmitEmpty), Collapsible: cont(val, tagCollapsible), } t.Name, t.Ignore = func(v string) (string, bool) { if len(v) > 0 && v != "_" { return v, false } return "", true }(val[0]) return t, true } // TagName used by structs from the ActivityPub package to Marshal and Unmarshal to/from JSON-LD func TagName(n string, tag Tag) string { if len(tag.Name) > 0 { return tag.Name } return n } // An UnsupportedTypeError is returned by Marshal when attempting // to encode an unsupported value type. type UnsupportedTypeError struct { Type reflect.Type } // Marshal returns the JSON encoding of v. // // Marshal traverses the value v recursively. // If an encountered value implements the Marshaler interface // and is not a nil pointer, Marshal calls its MarshalJSON method // to produce JSON. If no MarshalJSON method is present but the // value implements encoding.TextMarshaler instead, Marshal calls // its MarshalText method and encodes the result as a JSON string. // The nil pointer exception is not strictly necessary // but mimics a similar, necessary exception in the behavior of // UnmarshalJSON. // // Otherwise, Marshal uses the following type-dependent default encodings: // // Boolean values encode as JSON booleans. // // Floating point, integer, and Number values encode as JSON numbers. // // String values encode as JSON strings coerced to valid UTF-8, // replacing invalid bytes with the Unicode replacement rune. // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" // to keep some browsers from misinterpreting JSON output as HTML. // Ampersand "&" is also escaped to "\u0026" for the same reason. // This escaping can be disabled using an Encoder that had SetEscapeHTML(false) // called on it. // // Array and slice values encode as JSON arrays, except that // []byte encodes as a base64-encoded string, and a nil slice // encodes as the null JSON value. // // Struct values encode as JSON objects. // Each exported struct field becomes a member of the object, using the // field name as the object key, unless the field is omitted for one of the // reasons given below. // // The encoding of each struct field can be customized by the format string // stored under the tagLabel + "" key in the struct field's tag. // The format string gives the name of the field, possibly followed by a // comma-separated list of options. The name may be empty in order to // specify options without overriding the default field name. // // The "omitempty" option specifies that the field should be omitted // from the encoding if the field has an empty value, defined as // false, 0, a nil pointer, a nil interface value, and any empty array, // slice, map, or string. // // As a special case, if the field tag is "-", the field is always omitted. // Note that a field with name "-" can still be generated using the tag "-,". // // Examples of struct field tags and their meanings: // // // Field appears in JSON as key "myName". // Field int `json:"myName"` // // // Field appears in JSON as key "myName" and // // the field is omitted from the object if its value is empty, // // as defined above. // Field int `json:"myName,omitempty"` // // // Field appears in JSON as key "Field" (the default), but // // the field is skipped if empty. // // Note the leading comma. // Field int `json:",omitempty"` // // // Field is ignored by this package. // Field int `json:"-"` // // // Field appears in JSON as key "-". // Field int `json:"-,"` // // The "string" option signals that a field is stored as JSON inside a // JSON-encoded string. It applies only to fields of string, floating point, // integer, or boolean types. This extra level of encoding is sometimes used // when communicating with JavaScript programs: // // Int64String int64 `json:",string"` // // The key name will be used if it's a non-empty string consisting of // only Unicode letters, digits, and ASCII punctuation except quotation // marks, backslash, and comma. // // Anonymous struct fields are usually marshaled as if their inner exported fields // were fields in the outer struct, subject to the usual Go visibility rules amended // as described in the next paragraph. // An anonymous struct field with a name given in its JSON tag is treated as // having that name, rather than being anonymous. // An anonymous struct field of interface type is treated the same as having // that type as its name, rather than being anonymous. // // The Go visibility rules for struct fields are amended for JSON when // deciding which field to marshal or unmarshal. If there are // multiple fields at the same level, and that level is the least // nested (and would therefore be the nesting level selected by the // usual Go rules), the following extra rules apply: // // 1) Of those fields, if any are JSON-tagged, only tagged fields are considered, // even if there are multiple untagged fields that would otherwise conflict. // // 2) If there is exactly one field (tagged or not according to the first rule), that is selected. // // 3) Otherwise there are multiple fields, and all are ignored; no error occurs. // // Handling of anonymous struct fields is new in Go 1.1. // Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of // an anonymous struct field in both current and earlier versions, give the field // a JSON tag of "-". // // Map values encode as JSON objects. The map's key type must either be a // string, an integer type, or implement encoding.TextMarshaler. The map keys // are sorted and used as JSON object keys by applying the following rules, // subject to the UTF-8 coercion described for string values above: // - string keys are used directly // - encoding.TextMarshalers are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. // A nil pointer encodes as the null JSON value. // // Interface values encode as the value contained in the interface. // A nil interface value encodes as the null JSON value. // // Channel, complex, and function values cannot be encoded in JSON. // Attempting to encode such a value causes Marshal to return // an UnsupportedTypeError. // // JSON cannot represent cyclic data structures and Marshal does not // handle them. Passing cyclic structures to Marshal will result in // an infinite recursion. func Marshal(v interface{}) ([]byte, error) { e := &encodeState{} err := e.marshal(v, encOpts{escapeHTML: true}) if err != nil { return nil, err } output := e.Bytes() typ := reflect.TypeOf(v) if typ.Kind() == reflect.Ptr { typ = typ.Elem() } if typ == payloadType { // @todo(marius): fix this ugly hack output = bytes.Replace(output, []byte(`,"Obj":{`), []byte(","), 1) output = output[:len(output)-1] } return output, nil } func (e *UnsupportedTypeError) Error() string { return tagLabel + ": unsupported type: " + e.Type.String() } type UnsupportedValueError struct { Value reflect.Value Str string } func (e *UnsupportedValueError) Error() string { return tagLabel + ": unsupported value: " + e.Str } // Before Go 1.2, an InvalidUTF8Error was returned by Marshal when // attempting to encode a string value with invalid UTF-8 sequences. // As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by // replacing invalid bytes with the Unicode replacement rune U+FFFD. // This error is no longer generated but is kept for backwards compatibility // with programs that might mention it. type InvalidUTF8Error struct { S string // the whole string value that caused the error } func (e *InvalidUTF8Error) Error() string { return tagLabel + ": invalid UTF-8 in string: " + strconv.Quote(e.S) } type MarshalerError struct { Type reflect.Type Err error } func (e *MarshalerError) Error() string { return tagLabel + ": error calling MarshalJSON for type " + e.Type.String() + ": " + e.Err.Error() } var hex = "0123456789abcdef" // An encodeState encodes JSON into a bytes.Buffer. type encodeState struct { bytes.Buffer // accumulated output scratch [64]byte } var encodeStatePool sync.Pool func newEncodeState() *encodeState { if v := encodeStatePool.Get(); v != nil { e := v.(*encodeState) e.Reset() return e } return new(encodeState) } func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) { defer func() { if r := recover(); r != nil { if _, ok := r.(runtime.Error); ok { panic(r) } if s, ok := r.(string); ok { panic(s) } err = r.(error) } }() e.reflectValue(reflect.ValueOf(v), opts) return nil } func (e *encodeState) error(err error) { panic(err) } func isEmptyValue(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: return v.Len() == 0 case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Interface, reflect.Ptr: return v.IsNil() case reflect.Struct: // this is important as it removes structs containing only empty elements // to ensure that the jsonld message is not extra verbose with valueless properties return func(reflect.Value) bool { var ret bool = true for i := 0; i < v.NumField(); i++ { ret = ret && isEmptyValue(v.Field(i)) } return ret }(v) } return false } func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) { valueEncoder(v)(e, v, opts) } type encOpts struct { // quoted causes primitive fields to be encoded inside JSON strings. quoted bool // escapeHTML causes '<', '>', and '&' to be escaped in JSON strings. escapeHTML bool } type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts) var encoderCache sync.Map // map[reflect.Type]encoderFunc func valueEncoder(v reflect.Value) encoderFunc { if !v.IsValid() { return invalidValueEncoder } return typeEncoder(v.Type()) } func typeEncoder(t reflect.Type) encoderFunc { if fi, ok := encoderCache.Load(t); ok { return fi.(encoderFunc) } // To deal with recursive types, populate the map with an // indirect func before we build it. This type waits on the // real func (f) to be ready and then calls it. This indirect // func is only used for recursive types. var ( wg sync.WaitGroup f encoderFunc ) wg.Add(1) fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) { wg.Wait() f(e, v, opts) })) if loaded { return fi.(encoderFunc) } // Compute the real encoder and replace the indirect func with it. f = newTypeEncoder(t, true) wg.Done() encoderCache.Store(t, f) return f } var ( marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem() textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem() ) // newTypeEncoder constructs an encoderFunc for a type. // The returned encoder only checks CanAddr when allowAddr is true. func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { if t.Implements(marshalerType) { return marshalerEncoder } if t.Kind() != reflect.Ptr && allowAddr { if reflect.PtrTo(t).Implements(marshalerType) { return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false)) } } if t.Implements(textMarshalerType) { return textMarshalerEncoder } if t.Kind() != reflect.Ptr && allowAddr { if reflect.PtrTo(t).Implements(textMarshalerType) { return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false)) } } switch t.Kind() { case reflect.Bool: return boolEncoder case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return intEncoder case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return uintEncoder case reflect.Float32: return float32Encoder case reflect.Float64: return float64Encoder case reflect.String: return stringEncoder case reflect.Interface: return interfaceEncoder case reflect.Struct: return newStructEncoder(t) case reflect.Map: return newMapEncoder(t) case reflect.Slice: return newSliceEncoder(t) case reflect.Array: return newArrayEncoder(t) case reflect.Ptr: return newPtrEncoder(t) default: return unsupportedTypeEncoder } } func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) { e.WriteString("null") } func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { if v.Kind() == reflect.Ptr && v.IsNil() { e.WriteString("null") return } m, ok := v.Interface().(json.Marshaler) if !ok { e.WriteString("null") return } b, err := m.MarshalJSON() if err == nil { // copy JSON into buffer, checking validity. err = json.Compact(&e.Buffer, b) } if err != nil { e.error(&MarshalerError{v.Type(), err}) } } func addrMarshalerEncoder(e *encodeState, v reflect.Value, _ encOpts) { va := v.Addr() if va.IsNil() { e.WriteString("null") return } m := va.Interface().(json.Marshaler) b, err := m.MarshalJSON() if err == nil { // copy JSON into buffer, checking validity. err = json.Compact(&e.Buffer, b) } if err != nil { e.error(&MarshalerError{v.Type(), err}) } } func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { if v.Kind() == reflect.Ptr && v.IsNil() { e.WriteString("null") return } m := v.Interface().(encoding.TextMarshaler) b, err := m.MarshalText() if err != nil { e.error(&MarshalerError{v.Type(), err}) } e.stringBytes(b, opts.escapeHTML) } func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { va := v.Addr() if va.IsNil() { e.WriteString("null") return } m := va.Interface().(encoding.TextMarshaler) b, err := m.MarshalText() if err != nil { e.error(&MarshalerError{v.Type(), err}) } e.stringBytes(b, opts.escapeHTML) } func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) { if opts.quoted { e.WriteByte('"') } if v.Bool() { e.WriteString("true") } else { e.WriteString("false") } if opts.quoted { e.WriteByte('"') } } func intEncoder(e *encodeState, v reflect.Value, opts encOpts) { b := strconv.AppendInt(e.scratch[:0], v.Int(), 10) if opts.quoted { e.WriteByte('"') } e.Write(b) if opts.quoted { e.WriteByte('"') } } func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) { b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10) if opts.quoted { e.WriteByte('"') } e.Write(b) if opts.quoted { e.WriteByte('"') } } type floatEncoder int // number of bits func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { f := v.Float() if math.IsInf(f, 0) || math.IsNaN(f) { e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))}) } // Convert as if by ES6 number to string conversion. // This matches most other JSON generators. // See golang.org/issue/6384 and golang.org/issue/14135. // Like fmt %g, but the exponent cutoffs are different // and exponents themselves are not padded to two digits. b := e.scratch[:0] abs := math.Abs(f) fmt := byte('f') // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. if abs != 0 { if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { fmt = 'e' } } b = strconv.AppendFloat(b, f, fmt, -1, int(bits)) if fmt == 'e' { // clean up e-09 to e-9 n := len(b) if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' { b[n-2] = b[n-1] b = b[:n-1] } } if opts.quoted { e.WriteByte('"') } e.Write(b) if opts.quoted { e.WriteByte('"') } } var ( float32Encoder = (floatEncoder(32)).encode float64Encoder = (floatEncoder(64)).encode ) func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) { if v.Type() == numberType { numStr := v.String() // In Go1.5 the empty string encodes to "0", while this is not a valid number literal // we keep compatibility so check validity after this. if numStr == "" { numStr = "0" // Number's zero-val } if !isValidNumber(numStr) { e.error(fmt.Errorf(tagLabel+": invalid number literal %q", numStr)) } e.WriteString(numStr) return } if opts.quoted { sb, err := Marshal(v.String()) if err != nil { e.error(err) } e.string(string(sb), opts.escapeHTML) } else { e.string(v.String(), opts.escapeHTML) } } func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) { if v.IsNil() { e.WriteString("null") return } e.reflectValue(v.Elem(), opts) } func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) { e.error(&UnsupportedTypeError{v.Type()}) } type structEncoder struct { fields []field fieldEncs []encoderFunc } func (se *structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { e.WriteByte('{') first := true for i, f := range se.fields { fv := fieldByIndex(v, f.index) if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) { continue } if first { first = false } else { e.WriteByte(',') } // TODO(marius): how bad is this? //opts.Collapsible = f.Collapsible /* if f.Collapsible { collapsingMethod := fv.MethodByName("Collapse") if !collapsingMethod.IsValid() || collapsingMethod.IsNil() { continue } e.string(f.Name, opts.escapeHTML) e.WriteByte(':') content := collapsingMethod.Call(nil)[0].Bytes() e.Write(content) continue } */ e.string(f.name, opts.escapeHTML) e.WriteByte(':') opts.quoted = f.quoted se.fieldEncs[i](e, fv, opts) } e.WriteByte('}') } func newStructEncoder(t reflect.Type) encoderFunc { fields := cachedTypeFields(t) se := &structEncoder{ fields: fields, fieldEncs: make([]encoderFunc, len(fields)), } for i, f := range fields { se.fieldEncs[i] = typeEncoder(typeByIndex(t, f.index)) } return se.encode } type mapEncoder struct { elemEnc encoderFunc } func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { if v.IsNil() { e.WriteString("null") return } e.WriteByte('{') // Extract and sort the keys. keys := v.MapKeys() sv := make([]reflectWithString, len(keys)) for i, v := range keys { sv[i].v = v if err := sv[i].resolve(); err != nil { e.error(&MarshalerError{v.Type(), err}) } } sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s }) for i, kv := range sv { if i > 0 { e.WriteByte(',') } e.string(kv.s, opts.escapeHTML) e.WriteByte(':') me.elemEnc(e, v.MapIndex(kv.v), opts) } e.WriteByte('}') } func newMapEncoder(t reflect.Type) encoderFunc { switch t.Key().Kind() { case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: default: if !t.Key().Implements(textMarshalerType) { return unsupportedTypeEncoder } } me := &mapEncoder{typeEncoder(t.Elem())} return me.encode } func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) { if v.IsNil() { e.WriteString("null") return } s := v.Bytes() e.WriteByte('"') if len(s) < 1024 { // for small buffers, using Encode directly is much faster. dst := make([]byte, base64.StdEncoding.EncodedLen(len(s))) base64.StdEncoding.Encode(dst, s) e.Write(dst) } else { // for large buffers, avoid unnecessary extra temporary // buffer space. enc := base64.NewEncoder(base64.StdEncoding, e) enc.Write(s) enc.Close() } e.WriteByte('"') } // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil. type sliceEncoder struct { arrayEnc encoderFunc } func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { if v.IsNil() { e.WriteString("null") return } se.arrayEnc(e, v, opts) } func newSliceEncoder(t reflect.Type) encoderFunc { // Byte slices get special treatment; arrays don't. if t.Elem().Kind() == reflect.Uint8 { p := reflect.PtrTo(t.Elem()) if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) { return encodeByteSlice } } enc := &sliceEncoder{newArrayEncoder(t)} return enc.encode } type arrayEncoder struct { elemEnc encoderFunc } func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { e.WriteByte('[') n := v.Len() for i := 0; i < n; i++ { if i > 0 { e.WriteByte(',') } ae.elemEnc(e, v.Index(i), opts) } e.WriteByte(']') } func newArrayEncoder(t reflect.Type) encoderFunc { enc := &arrayEncoder{typeEncoder(t.Elem())} return enc.encode } type ptrEncoder struct { elemEnc encoderFunc } func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { if v.IsNil() { e.WriteString("null") return } pe.elemEnc(e, v.Elem(), opts) } func newPtrEncoder(t reflect.Type) encoderFunc { enc := &ptrEncoder{typeEncoder(t.Elem())} return enc.encode } type condAddrEncoder struct { canAddrEnc, elseEnc encoderFunc } func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) { if v.CanAddr() { ce.canAddrEnc(e, v, opts) } else { ce.elseEnc(e, v, opts) } } // newCondAddrEncoder returns an encoder that checks whether its value // CanAddr and delegates to canAddrEnc if so, else to elseEnc. func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc { enc := &condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc} return enc.encode } func isValidTag(s string) bool { if s == "" { return false } for _, c := range s { switch { case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): // Backslash and quote chars are reserved, but // otherwise any punctuation chars are allowed // in a tag name. default: if !unicode.IsLetter(c) && !unicode.IsDigit(c) { return false } } } return true } func fieldByIndex(v reflect.Value, index []int) reflect.Value { for _, i := range index { if v.Kind() == reflect.Ptr { if v.IsNil() { return reflect.Value{} } v = v.Elem() } v = v.Field(i) } return v } func typeByIndex(t reflect.Type, index []int) reflect.Type { for _, i := range index { if t.Kind() == reflect.Ptr { t = t.Elem() } t = t.Field(i).Type } return t } type reflectWithString struct { v reflect.Value s string } func (w *reflectWithString) resolve() error { if w.v.Kind() == reflect.String { w.s = w.v.String() return nil } if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok { buf, err := tm.MarshalText() w.s = string(buf) return err } switch w.v.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: w.s = strconv.FormatInt(w.v.Int(), 10) return nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: w.s = strconv.FormatUint(w.v.Uint(), 10) return nil } panic("unexpected map key type") } // NOTE: keep in sync with stringBytes below. func (e *encodeState) string(s string, escapeHTML bool) int { len0 := e.Len() e.WriteByte('"') start := 0 for i := 0; i < len(s); { if b := s[i]; b < utf8.RuneSelf { if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { i++ continue } if start < i { e.WriteString(s[start:i]) } switch b { case '\\', '"': e.WriteByte('\\') e.WriteByte(b) case '\n': e.WriteByte('\\') e.WriteByte('n') case '\r': e.WriteByte('\\') e.WriteByte('r') case '\t': e.WriteByte('\\') e.WriteByte('t') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. e.WriteString(`\u00`) e.WriteByte(hex[b>>4]) e.WriteByte(hex[b&0xF]) } i++ start = i continue } c, size := utf8.DecodeRuneInString(s[i:]) if c == utf8.RuneError && size == 1 { if start < i { e.WriteString(s[start:i]) } e.WriteString(`\ufffd`) i += size start = i continue } // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. if c == '\u2028' || c == '\u2029' { if start < i { e.WriteString(s[start:i]) } e.WriteString(`\u202`) e.WriteByte(hex[c&0xF]) i += size start = i continue } i += size } if start < len(s) { e.WriteString(s[start:]) } e.WriteByte('"') return e.Len() - len0 } // NOTE: keep in sync with string above. func (e *encodeState) stringBytes(s []byte, escapeHTML bool) int { len0 := e.Len() e.WriteByte('"') start := 0 for i := 0; i < len(s); { if b := s[i]; b < utf8.RuneSelf { if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) { i++ continue } if start < i { e.Write(s[start:i]) } switch b { case '\\', '"': e.WriteByte('\\') e.WriteByte(b) case '\n': e.WriteByte('\\') e.WriteByte('n') case '\r': e.WriteByte('\\') e.WriteByte('r') case '\t': e.WriteByte('\\') e.WriteByte('t') default: // This encodes bytes < 0x20 except for \t, \n and \r. // If escapeHTML is set, it also escapes <, >, and & // because they can lead to security holes when // user-controlled strings are rendered into JSON // and served to some browsers. e.WriteString(`\u00`) e.WriteByte(hex[b>>4]) e.WriteByte(hex[b&0xF]) } i++ start = i continue } c, size := utf8.DecodeRune(s[i:]) if c == utf8.RuneError && size == 1 { if start < i { e.Write(s[start:i]) } e.WriteString(`\ufffd`) i += size start = i continue } // U+2028 is LINE SEPARATOR. // U+2029 is PARAGRAPH SEPARATOR. // They are both technically valid characters in JSON strings, // but don't work in JSONP, which has to be evaluated as JavaScript, // and can lead to security holes there. It is valid JSON to // escape them, so we do so unconditionally. // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion. if c == '\u2028' || c == '\u2029' { if start < i { e.Write(s[start:i]) } e.WriteString(`\u202`) e.WriteByte(hex[c&0xF]) i += size start = i continue } i += size } if start < len(s) { e.Write(s[start:]) } e.WriteByte('"') return e.Len() - len0 } // A field represents a single field found in a struct. type field struct { name string nameBytes []byte // []byte(Name) equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent tag bool index []int typ reflect.Type omitEmpty bool collapsible bool quoted bool } func fillField(f field) field { f.nameBytes = []byte(f.name) f.equalFold = foldFunc(f.nameBytes) return f } // byIndex sorts field by index sequence. type byIndex []field func (x byIndex) Len() int { return len(x) } func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } func (x byIndex) Less(i, j int) bool { for k, xik := range x[i].index { if k >= len(x[j].index) { return false } if xik != x[j].index[k] { return xik < x[j].index[k] } } return len(x[i].index) < len(x[j].index) } // typeFields returns a list of fields that JSON should recognize for the given type. // The algorithm is breadth-first search over the set of structs to include - the top struct // and then any reachable anonymous structs. func typeFields(t reflect.Type) []field { // Anonymous fields to explore at the current level and the next. current := []field{} next := []field{{typ: t}} // Count of queued names for current level and the next. count := map[reflect.Type]int{} nextCount := map[reflect.Type]int{} // Types already visited at an earlier level. visited := map[reflect.Type]bool{} // Fields found. var fields []field for len(next) > 0 { current, next = next, current[:0] count, nextCount = nextCount, map[reflect.Type]int{} for _, f := range current { if visited[f.typ] { continue } visited[f.typ] = true // Scan f.typ for fields to include. for i := 0; i < f.typ.NumField(); i++ { sf := f.typ.Field(i) if sf.Anonymous { t := sf.Type if t.Kind() == reflect.Ptr { t = t.Elem() } // If embedded, StructField.PkgPath is not a reliable // indicator of whether the field is exported. // See https://golang.org/issue/21122 if !isExported(t.Name()) && t.Kind() != reflect.Struct { // Ignore embedded fields of unexported non-struct types. // Do not ignore embedded fields of unexported struct types // since they may have exported fields. continue } } else if sf.PkgPath != "" { // Ignore unexported non-embedded fields. continue } tag := sf.Tag.Get(tagLabel) if tag == "-" { continue } name, opts := parseTag(tag) if !isValidTag(name) { name = "" } index := make([]int, len(f.index)+1) copy(index, f.index) index[len(f.index)] = i ft := sf.Type if ft.Name() == "" && ft.Kind() == reflect.Ptr { // Follow pointer. ft = ft.Elem() } // Only strings, floats, integers, and booleans can be quoted. quoted := false if opts.Contains("string") { switch ft.Kind() { case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: quoted = true } } // Record found field and index sequence. if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { tagged := name != "" if name == "" { name = sf.Name } fields = append(fields, fillField(field{ name: name, tag: tagged, index: index, typ: ft, omitEmpty: opts.Contains(tagOmitEmpty), collapsible: opts.Contains(tagCollapsible), quoted: quoted, })) if count[f.typ] > 1 { // If there were multiple instances, add a second, // so that the annihilation code will see a duplicate. // It only cares about the distinction between 1 or 2, // so don't bother generating any more copies. fields = append(fields, fields[len(fields)-1]) } continue } // Record new anonymous struct to explore in next round. nextCount[ft]++ if nextCount[ft] == 1 { next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft})) } } } } sort.Slice(fields, func(i, j int) bool { x := fields // sort field by name, breaking ties with depth, then // breaking ties with "name came from json tag", then // breaking ties with index sequence. if x[i].name != x[j].name { return x[i].name < x[j].name } if len(x[i].index) != len(x[j].index) { return len(x[i].index) < len(x[j].index) } if x[i].tag != x[j].tag { return x[i].tag } return byIndex(x).Less(i, j) }) // Delete all fields that are hidden by the Go rules for embedded fields, // except that fields with JSON tags are promoted. // The fields are sorted in primary order of name, secondary order // of field index length. Loop over names; for each name, delete // hidden fields by choosing the one dominant field that survives. out := fields[:0] for advance, i := 0, 0; i < len(fields); i += advance { // One iteration per name. // Find the sequence of fields with the name of this first field. fi := fields[i] name := fi.name for advance = 1; i+advance < len(fields); advance++ { fj := fields[i+advance] if fj.name != name { break } } if advance == 1 { // Only one field with this name out = append(out, fi) continue } dominant, ok := dominantField(fields[i : i+advance]) if ok { out = append(out, dominant) } } fields = out sort.Sort(byIndex(fields)) return fields } // isExported reports whether the identifier is exported. func isExported(id string) bool { r, _ := utf8.DecodeRuneInString(id) return unicode.IsUpper(r) } // dominantField looks through the fields, all of which are known to // have the same name, to find the single field that dominates the // others using Go's embedding rules, modified by the presence of // JSON tags. If there are multiple top-level fields, the boolean // will be false: This condition is an error in Go and we skip all // the fields. func dominantField(fields []field) (field, bool) { // The fields are sorted in increasing index-length order. The winner // must therefore be one with the shortest index length. Drop all // longer entries, which is easy: just truncate the slice. length := len(fields[0].index) tagged := -1 // Index of first tagged field. for i, f := range fields { if len(f.index) > length { fields = fields[:i] break } if f.tag { if tagged >= 0 { // Multiple tagged fields at the same level: conflict. // Return no field. return field{}, false } tagged = i } } if tagged >= 0 { return fields[tagged], true } // All remaining fields have the same length. If there's more than one, // we have a conflict (two fields named "X" at the same level) and we // return no field. if len(fields) > 1 { return field{}, false } return fields[0], true } var fieldCache struct { value atomic.Value // map[reflect.Type][]field mu sync.Mutex // used only by writers } // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. func cachedTypeFields(t reflect.Type) []field { m, _ := fieldCache.value.Load().(map[reflect.Type][]field) f := m[t] if f != nil { return f } // Compute fields without lock. // Might duplicate effort but won't hold other computations back. f = typeFields(t) if f == nil { f = []field{} } fieldCache.mu.Lock() m, _ = fieldCache.value.Load().(map[reflect.Type][]field) newM := make(map[reflect.Type][]field, len(m)+1) for k, v := range m { newM[k] = v } newM[t] = f fieldCache.value.Store(newM) fieldCache.mu.Unlock() return f }
-
-
jsonld/encode_test.go (deleted)
-
@@ -1,140 +0,0 @@package jsonld import ( "bytes" "reflect" "strings" "testing" ) type mockBase struct { Id string Name string Type string } type mockTypeA struct { mockBase PropA string PropB float32 } func TestMarshal(t *testing.T) { a := mockTypeA{mockBase{"base_id", "MockObjA", "mock_obj"}, "prop_a", 0.001} b := mockTypeA{} url := "http://www.habarnam.ro" p := WithContext(IRI(url)) var err error var out []byte out, err = p.Marshal(a) if err != nil { t.Errorf("%s", err) } if !strings.Contains(string(out), string(ContextKw)) { t.Errorf("Context name not found %q in %s", ContextKw, out) } if !strings.Contains(string(out), url) { t.Errorf("Context url not found %q in %s", url, out) } err = Unmarshal(out, &b) if err != nil { t.Errorf("%s", err) } if a.Id != b.Id { t.Errorf("Id isn't equal %q expected %q in %s", a.Id, b.Id, out) } if a.Name != b.Name { t.Errorf("Name isn't equal %q expected %q", a.Name, b.Name) } if a.Type != b.Type { t.Errorf("Type isn't equal %q expected %q", a.Type, b.Type) } if a.PropA != b.PropA { t.Errorf("PropA isn't equal %q expected %q", a.PropA, b.PropA) } if a.PropB != b.PropB { t.Errorf("PropB isn't equal %f expected %f", a.PropB, b.PropB) } } func TestMarshalNullContext(t *testing.T) { var a = struct { PropA string PropB float64 }{"test", 0.0004} outL, errL := Marshal(a) if errL != nil { t.Errorf("%s", errL) } outJ, errJ := Marshal(a) if errJ != nil { t.Errorf("%s", errJ) } if !bytes.Equal(outL, outJ) { t.Errorf("Json output should be euqlal %q, received %q", outL, outJ) } } func TestIsEmpty(t *testing.T) { var a int if !isEmptyValue(reflect.ValueOf(a)) { t.Errorf("Invalid empty value %v", a) } if !isEmptyValue(reflect.ValueOf(uint(a))) { t.Errorf("Invalid empty value %v", uint(a)) } var b float64 if !isEmptyValue(reflect.ValueOf(b)) { t.Errorf("Invalid empty value %v", b) } var c string if !isEmptyValue(reflect.ValueOf(c)) { t.Errorf("Invalid empty value %s", c) } var d []byte if !isEmptyValue(reflect.ValueOf(d)) { t.Errorf("Invalid empty value %v", d) } var e *interface{} if !isEmptyValue(reflect.ValueOf(e)) { t.Errorf("Invalid empty value %v", e) } g := false if !isEmptyValue(reflect.ValueOf(g)) { t.Errorf("Invalid empty value %v", g) } h := true if isEmptyValue(reflect.ValueOf(h)) { t.Errorf("Invalid empty value %v", h) } } func TestWithContext_MarshalJSON(t *testing.T) { tv := "value_test" v := struct{ Test string }{Test: tv} data, err := WithContext(IRI("http://example.com")).Marshal(v) if err != nil { t.Error(err) } if !bytes.Contains(data, []byte(ContextKw)) { t.Errorf("%q not found in %s", ContextKw, data) } m := reflect.TypeOf(v) mv := reflect.ValueOf(v) for i := 0; i < m.NumField(); i++ { f := m.Field(i) v := mv.Field(i) if !bytes.Contains(data, []byte(f.Name)) { t.Errorf("%q not found in %s", f.Name, data) } if !bytes.Contains(data, []byte(v.String())) { t.Errorf("%q not found in %s", v.String(), data) } } }
-
-
jsonld/fold.go (deleted)
-
@@ -1,143 +0,0 @@// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import ( "bytes" "unicode/utf8" ) const ( caseMask = ^byte(0x20) // Mask to ignore case in ASCII. kelvin = '\u212a' smallLongEss = '\u017f' ) // foldFunc returns one of four different case folding equivalence // functions, from most general (and slow) to fastest: // // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') // 3) asciiEqualFold, no special, but includes non-letters (including _) // 4) simpleLetterEqualFold, no specials, no non-letters. // // The letters S and K are special because they map to 3 runes, not just 2: // * S maps to s and to U+017F 'ſ' Latin small letter long s // * k maps to K and to U+212A 'K' Kelvin sign // See https://play.golang.org/p/tTxjOc0OGo // // The returned function is specialized for matching against s and // should only be given s. It's not curried for performance reasons. func foldFunc(s []byte) func(s, t []byte) bool { nonLetter := false special := false // special letter for _, b := range s { if b >= utf8.RuneSelf { return bytes.EqualFold } upper := b & caseMask if upper < 'A' || upper > 'Z' { nonLetter = true } else if upper == 'K' || upper == 'S' { // See above for why these letters are special. special = true } } if special { return equalFoldRight } if nonLetter { return asciiEqualFold } return simpleLetterEqualFold } // equalFoldRight is a specialization of bytes.EqualFold when s is // known to be all ASCII (including punctuation), but contains an 's', // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. // See comments on foldFunc. func equalFoldRight(s, t []byte) bool { for _, sb := range s { if len(t) == 0 { return false } tb := t[0] if tb < utf8.RuneSelf { if sb != tb { sbUpper := sb & caseMask if 'A' <= sbUpper && sbUpper <= 'Z' { if sbUpper != tb&caseMask { return false } } else { return false } } t = t[1:] continue } // sb is ASCII and t is not. t must be either kelvin // sign or long s; sb must be s, S, k, or K. tr, size := utf8.DecodeRune(t) switch sb { case 's', 'S': if tr != smallLongEss { return false } case 'k', 'K': if tr != kelvin { return false } default: return false } t = t[size:] } if len(t) > 0 { return false } return true } // asciiEqualFold is a specialization of bytes.EqualFold for use when // s is all ASCII (but may contain non-letters) and contains no // special-folding letters. // See comments on foldFunc. func asciiEqualFold(s, t []byte) bool { if len(s) != len(t) { return false } for i, sb := range s { tb := t[i] if sb == tb { continue } if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { if sb&caseMask != tb&caseMask { return false } } else { return false } } return true } // simpleLetterEqualFold is a specialization of bytes.EqualFold for // use when s is all ASCII letters (no underscores, etc) and also // doesn't contain 'k', 'K', 's', or 'S'. // See comments on foldFunc. func simpleLetterEqualFold(s, t []byte) bool { if len(s) != len(t) { return false } for i, b := range s { if b&caseMask != t[i]&caseMask { return false } } return true }
-
-
jsonld/fold_test.go (deleted)
-
@@ -1,116 +0,0 @@// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import ( "bytes" "strings" "testing" "unicode/utf8" ) var foldTests = []struct { fn func(s, t []byte) bool s, t string want bool }{ {equalFoldRight, "", "", true}, {equalFoldRight, "a", "a", true}, {equalFoldRight, "", "a", false}, {equalFoldRight, "a", "", false}, {equalFoldRight, "a", "A", true}, {equalFoldRight, "AB", "ab", true}, {equalFoldRight, "AB", "ac", false}, {equalFoldRight, "sbkKc", "ſbKKc", true}, {equalFoldRight, "SbKkc", "ſbKKc", true}, {equalFoldRight, "SbKkc", "ſbKK", false}, {equalFoldRight, "e", "é", false}, {equalFoldRight, "s", "S", true}, {simpleLetterEqualFold, "", "", true}, {simpleLetterEqualFold, "abc", "abc", true}, {simpleLetterEqualFold, "abc", "ABC", true}, {simpleLetterEqualFold, "abc", "ABCD", false}, {simpleLetterEqualFold, "abc", "xxx", false}, {asciiEqualFold, "a_B", "A_b", true}, {asciiEqualFold, "aa@", "aa`", false}, // verify 0x40 and 0x60 aren't case-equivalent } func TestFold(t *testing.T) { for i, tt := range foldTests { if got := tt.fn([]byte(tt.s), []byte(tt.t)); got != tt.want { t.Errorf("%d. %q, %q = %v; want %v", i, tt.s, tt.t, got, tt.want) } truth := strings.EqualFold(tt.s, tt.t) if truth != tt.want { t.Errorf("strings.EqualFold doesn't agree with case %d", i) } } } func TestFoldAgainstUnicode(t *testing.T) { const bufSize = 5 buf1 := make([]byte, 0, bufSize) buf2 := make([]byte, 0, bufSize) var runes []rune for i := 0x20; i <= 0x7f; i++ { runes = append(runes, rune(i)) } runes = append(runes, kelvin, smallLongEss) funcs := []struct { name string fold func(s, t []byte) bool letter bool // must be ASCII letter simple bool // must be simple ASCII letter (not 'S' or 'K') }{ { name: "equalFoldRight", fold: equalFoldRight, }, { name: "asciiEqualFold", fold: asciiEqualFold, simple: true, }, { name: "simpleLetterEqualFold", fold: simpleLetterEqualFold, simple: true, letter: true, }, } for _, ff := range funcs { for _, r := range runes { if r >= utf8.RuneSelf { continue } if ff.letter && !isASCIILetter(byte(r)) { continue } if ff.simple && (r == 's' || r == 'S' || r == 'k' || r == 'K') { continue } for _, r2 := range runes { buf1 := append(buf1[:0], 'x') buf2 := append(buf2[:0], 'x') buf1 = buf1[:1+utf8.EncodeRune(buf1[1:bufSize], r)] buf2 = buf2[:1+utf8.EncodeRune(buf2[1:bufSize], r2)] buf1 = append(buf1, 'x') buf2 = append(buf2, 'x') want := bytes.EqualFold(buf1, buf2) if got := ff.fold(buf1, buf2); got != want { t.Errorf("%s(%q, %q) = %v; want %v", ff.name, buf1, buf2, got, want) } } } } } func isASCIILetter(b byte) bool { return ('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') }
-
-
jsonld/scanner.go (deleted)
-
@@ -1,632 +0,0 @@// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld // JSON value parser state machine. // Just about at the limit of what is reasonable to write by hand. // Some parts are a bit tedious, but overall it nicely factors out the // otherwise common code from the multiple scanning functions // in this package (Compact, Indent, checkValid, nextValue, etc). // // This file starts with two simple examples using the scanner // before diving into the scanner itself. import ( "strconv" ) // Valid reports whether data is a valid JSON encoding. func Valid(data []byte) bool { return checkValid(data, &scanner{}) == nil } // checkValid verifies that data is valid JSON-encoded data. // scan is passed in for use by checkValid to avoid an allocation. func checkValid(data []byte, scan *scanner) error { scan.reset() for _, c := range data { scan.bytes++ if scan.step(scan, c) == scanError { return scan.err } } if scan.eof() == scanError { return scan.err } return nil } // nextValue splits data after the next whole JSON value, // returning that value and the bytes that follow it as separate slices. // scan is passed in for use by nextValue to avoid an allocation. func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) { scan.reset() for i, c := range data { v := scan.step(scan, c) if v >= scanEndObject { switch v { // probe the scanner with a space to determine whether we will // get scanEnd on the next character. Otherwise, if the next character // is not a space, scanEndTop allocates a needless error. case scanEndObject, scanEndArray: if scan.step(scan, ' ') == scanEnd { return data[:i+1], data[i+1:], nil } case scanError: return nil, nil, scan.err case scanEnd: return data[:i], data[i:], nil } } } if scan.eof() == scanError { return nil, nil, scan.err } return data, nil, nil } // A SyntaxError is a description of a JSON syntax error. type SyntaxError struct { msg string // description of error Offset int64 // error occurred after reading Offset bytes } func (e *SyntaxError) Error() string { return e.msg } // A scanner is a JSON scanning state machine. // Callers call scan.reset() and then pass bytes in one at a time // by calling scan.step(&scan, c) for each byte. // The return value, referred to as an opcode, tells the // caller about significant parsing events like beginning // and ending literals, objects, and arrays, so that the // caller can follow along if it wishes. // The return value scanEnd indicates that a single top-level // JSON value has been completed, *before* the byte that // just got passed in. (The indication must be delayed in order // to recognize the end of numbers: is 123 a whole value or // the beginning of 12345e+6?). type scanner struct { // The step is a func to be called to execute the next transition. // Also tried using an integer constant and a single func // with a switch, but using the func directly was 10% faster // on a 64-bit Mac Mini, and it's nicer to read. step func(*scanner, byte) int // Reached end of top-level value. endTop bool // Stack of what we're in the middle of - array values, object keys, object values. parseState []int // Error that happened, if any. err error // 1-byte redo (see undo method) redo bool redoCode int redoState func(*scanner, byte) int // total bytes consumed, updated by decoder.Decode bytes int64 } // These values are returned by the state transition functions // assigned to scanner.state and the method scanner.eof. // They give details about the current state of the scan that // callers might be interested to know about. // It is okay to Ignore the return value of any particular // call to scanner.state: if one call returns scanError, // every subsequent call will return scanError too. const ( // Continue. scanContinue = iota // uninteresting byte scanBeginLiteral // end implied by next result != scanContinue scanBeginObject // begin object scanObjectKey // just finished object key (string) scanObjectValue // just finished non-last object value scanEndObject // end object (implies scanObjectValue if possible) scanBeginArray // begin array scanArrayValue // just finished array value scanEndArray // end array (implies scanArrayValue if possible) scanSkipSpace // space byte; can skip; known to be last "continue" result // Stop. scanEnd // top-level value ended *before* this byte; known to be first "stop" result scanError // hit an error, scanner.err. scanFindType // need to find the "jsonld:type" element of the object. ) // These values are stored in the parseState stack. // They give the current state of a composite value // being scanned. If the parser is inside a nested value // the parseState describes the nested state, outermost at entry 0. const ( parseObjectKey = iota // parsing object key (before colon) parseObjectValue // parsing object value (after colon) parseArrayValue // parsing array value ) // reset prepares the scanner for use. // It must be called before calling s.step. func (s *scanner) reset() { s.step = stateBeginValue s.parseState = s.parseState[0:0] s.err = nil s.redo = false s.endTop = false } // eof tells the scanner that the end of input has been reached. // It returns a scan status just as s.step does. func (s *scanner) eof() int { if s.err != nil { return scanError } if s.endTop { return scanEnd } s.step(s, ' ') if s.endTop { return scanEnd } if s.err == nil { s.err = &SyntaxError{"unexpected end of JSON input", s.bytes} } return scanError } // pushParseState pushes a new parse state p onto the parse stack. func (s *scanner) pushParseState(p int) { s.parseState = append(s.parseState, p) } // popParseState pops a parse state (already obtained) off the stack // and updates s.step accordingly. func (s *scanner) popParseState() { n := len(s.parseState) - 1 s.parseState = s.parseState[0:n] s.redo = false if n == 0 { s.step = stateEndTop s.endTop = true } else { s.step = stateEndValue } } func isSpace(c byte) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } // stateBeginValueOrEmpty is the state after reading `[`. func stateBeginValueOrEmpty(s *scanner, c byte) int { if c <= ' ' && isSpace(c) { return scanSkipSpace } if c == ']' { return stateEndValue(s, c) } return stateBeginValue(s, c) } // stateBeginValue is the state at the beginning of the input. func stateBeginValue(s *scanner, c byte) int { if c <= ' ' && isSpace(c) { return scanSkipSpace } switch c { case '{': s.step = stateBeginStringOrEmpty s.pushParseState(parseObjectKey) return scanBeginObject case '[': s.step = stateBeginValueOrEmpty s.pushParseState(parseArrayValue) return scanBeginArray case '"': s.step = stateInString return scanBeginLiteral case '-': s.step = stateNeg return scanBeginLiteral case '0': // beginning of 0.123 s.step = state0 return scanBeginLiteral case 't': // beginning of true s.step = stateT return scanBeginLiteral case 'f': // beginning of false s.step = stateF return scanBeginLiteral case 'n': // beginning of null s.step = stateN return scanBeginLiteral } if '1' <= c && c <= '9' { // beginning of 1234.5 s.step = state1 return scanBeginLiteral } return s.error(c, "looking for beginning of value") } // stateBeginStringOrEmpty is the state after reading `{`. func stateBeginStringOrEmpty(s *scanner, c byte) int { if c <= ' ' && isSpace(c) { return scanSkipSpace } if c == '}' { n := len(s.parseState) s.parseState[n-1] = parseObjectValue return stateEndValue(s, c) } return stateBeginString(s, c) } // stateBeginString is the state after reading `{"key": value,`. func stateBeginString(s *scanner, c byte) int { if c <= ' ' && isSpace(c) { return scanSkipSpace } if c == '"' { s.step = stateInString return scanBeginLiteral } return s.error(c, "looking for beginning of object key string") } // stateEndValue is the state after completing a value, // such as after reading `{}` or `true` or `["x"`. func stateEndValue(s *scanner, c byte) int { n := len(s.parseState) if n == 0 { // Completed top-level before the current byte. s.step = stateEndTop s.endTop = true return stateEndTop(s, c) } if c <= ' ' && isSpace(c) { s.step = stateEndValue return scanSkipSpace } ps := s.parseState[n-1] switch ps { case parseObjectKey: if c == ':' { s.parseState[n-1] = parseObjectValue s.step = stateBeginValue return scanObjectKey } return s.error(c, "after object key") case parseObjectValue: if c == ',' { s.parseState[n-1] = parseObjectKey s.step = stateBeginString return scanObjectValue } if c == '}' { s.popParseState() return scanEndObject } return s.error(c, "after object key:value pair") case parseArrayValue: if c == ',' { s.step = stateBeginValue return scanArrayValue } if c == ']' { s.popParseState() return scanEndArray } return s.error(c, "after array element") } return s.error(c, "") } // stateEndTop is the state after finishing the top-level value, // such as after reading `{}` or `[1,2,3]`. // Only space characters should be seen now. func stateEndTop(s *scanner, c byte) int { if c != ' ' && c != '\t' && c != '\r' && c != '\n' { // Complain about non-space byte on next call. s.error(c, "after top-level value") } return scanEnd } // stateInString is the state after reading `"`. func stateInString(s *scanner, c byte) int { if c == '"' { s.step = stateEndValue return scanContinue } if c == '\\' { s.step = stateInStringEsc return scanContinue } if c < 0x20 { return s.error(c, "in string literal") } return scanContinue } // stateInStringEsc is the state after reading `"\` during a quoted string. func stateInStringEsc(s *scanner, c byte) int { switch c { case 'b', 'f', 'n', 'r', 't', '\\', '/', '"': s.step = stateInString return scanContinue case 'u': s.step = stateInStringEscU return scanContinue } return s.error(c, "in string escape code") } // stateInStringEscU is the state after reading `"\u` during a quoted string. func stateInStringEscU(s *scanner, c byte) int { if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { s.step = stateInStringEscU1 return scanContinue } // numbers return s.error(c, "in \\u hexadecimal character escape") } // stateInStringEscU1 is the state after reading `"\u1` during a quoted string. func stateInStringEscU1(s *scanner, c byte) int { if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { s.step = stateInStringEscU12 return scanContinue } // numbers return s.error(c, "in \\u hexadecimal character escape") } // stateInStringEscU12 is the state after reading `"\u12` during a quoted string. func stateInStringEscU12(s *scanner, c byte) int { if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { s.step = stateInStringEscU123 return scanContinue } // numbers return s.error(c, "in \\u hexadecimal character escape") } // stateInStringEscU123 is the state after reading `"\u123` during a quoted string. func stateInStringEscU123(s *scanner, c byte) int { if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' { s.step = stateInString return scanContinue } // numbers return s.error(c, "in \\u hexadecimal character escape") } // stateNeg is the state after reading `-` during a number. func stateNeg(s *scanner, c byte) int { if c == '0' { s.step = state0 return scanContinue } if '1' <= c && c <= '9' { s.step = state1 return scanContinue } return s.error(c, "in numeric literal") } // state1 is the state after reading a non-zero integer during a number, // such as after reading `1` or `100` but not `0`. func state1(s *scanner, c byte) int { if '0' <= c && c <= '9' { s.step = state1 return scanContinue } return state0(s, c) } // state0 is the state after reading `0` during a number. func state0(s *scanner, c byte) int { if c == '.' { s.step = stateDot return scanContinue } if c == 'e' || c == 'E' { s.step = stateE return scanContinue } return stateEndValue(s, c) } // stateDot is the state after reading the integer and decimal point in a number, // such as after reading `1.`. func stateDot(s *scanner, c byte) int { if '0' <= c && c <= '9' { s.step = stateDot0 return scanContinue } return s.error(c, "after decimal point in numeric literal") } // stateDot0 is the state after reading the integer, decimal point, and subsequent // digits of a number, such as after reading `3.14`. func stateDot0(s *scanner, c byte) int { if '0' <= c && c <= '9' { return scanContinue } if c == 'e' || c == 'E' { s.step = stateE return scanContinue } return stateEndValue(s, c) } // stateE is the state after reading the mantissa and e in a number, // such as after reading `314e` or `0.314e`. func stateE(s *scanner, c byte) int { if c == '+' || c == '-' { s.step = stateESign return scanContinue } return stateESign(s, c) } // stateESign is the state after reading the mantissa, e, and sign in a number, // such as after reading `314e-` or `0.314e+`. func stateESign(s *scanner, c byte) int { if '0' <= c && c <= '9' { s.step = stateE0 return scanContinue } return s.error(c, "in exponent of numeric literal") } // stateE0 is the state after reading the mantissa, e, optional sign, // and at least one digit of the exponent in a number, // such as after reading `314e-2` or `0.314e+1` or `3.14e0`. func stateE0(s *scanner, c byte) int { if '0' <= c && c <= '9' { return scanContinue } return stateEndValue(s, c) } // stateT is the state after reading `t`. func stateT(s *scanner, c byte) int { if c == 'r' { s.step = stateTr return scanContinue } return s.error(c, "in literal true (expecting 'r')") } // stateTr is the state after reading `tr`. func stateTr(s *scanner, c byte) int { if c == 'u' { s.step = stateTru return scanContinue } return s.error(c, "in literal true (expecting 'u')") } // stateTru is the state after reading `tru`. func stateTru(s *scanner, c byte) int { if c == 'e' { s.step = stateEndValue return scanContinue } return s.error(c, "in literal true (expecting 'e')") } // stateF is the state after reading `f`. func stateF(s *scanner, c byte) int { if c == 'a' { s.step = stateFa return scanContinue } return s.error(c, "in literal false (expecting 'a')") } // stateFa is the state after reading `fa`. func stateFa(s *scanner, c byte) int { if c == 'l' { s.step = stateFal return scanContinue } return s.error(c, "in literal false (expecting 'l')") } // stateFal is the state after reading `fal`. func stateFal(s *scanner, c byte) int { if c == 's' { s.step = stateFals return scanContinue } return s.error(c, "in literal false (expecting 's')") } // stateFals is the state after reading `fals`. func stateFals(s *scanner, c byte) int { if c == 'e' { s.step = stateEndValue return scanContinue } return s.error(c, "in literal false (expecting 'e')") } // stateN is the state after reading `n`. func stateN(s *scanner, c byte) int { if c == 'u' { s.step = stateNu return scanContinue } return s.error(c, "in literal null (expecting 'u')") } // stateNu is the state after reading `nu`. func stateNu(s *scanner, c byte) int { if c == 'l' { s.step = stateNul return scanContinue } return s.error(c, "in literal null (expecting 'l')") } // stateNul is the state after reading `nul`. func stateNul(s *scanner, c byte) int { if c == 'l' { s.step = stateEndValue return scanContinue } return s.error(c, "in literal null (expecting 'l')") } // stateError is the state after reaching a syntax error, // such as after reading `[1}` or `5.1.2`. func stateError(s *scanner, c byte) int { return scanError } // error records an error and switches to the error state. func (s *scanner) error(c byte, context string) int { s.step = stateError s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes} return scanError } // quoteChar formats c as a quoted character literal func quoteChar(c byte) string { // special cases - different from quoted strings if c == '\'' { return `'\''` } if c == '"' { return `'"'` } // use quoted string with different quotation marks s := strconv.Quote(string(c)) return "'" + s[1:len(s)-1] + "'" } // undo causes the scanner to return scanCode from the next state transition. // This gives callers a simple 1-byte undo mechanism. func (s *scanner) undo(scanCode int) { if s.redo { panic("json: invalid use of scanner") } s.redoCode = scanCode s.redoState = s.step s.step = stateRedo s.redo = true } // stateRedo helps implement the scanner's 1-byte undo. func stateRedo(s *scanner, c byte) int { s.redo = false s.step = s.redoState return s.redoCode }
-
-
jsonld/scanner_test.go (deleted)
-
@@ -1,29 +0,0 @@// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import ( "testing" ) var validTests = []struct { data string ok bool }{ {`foo`, false}, {`}{`, false}, {`{]`, false}, {`{}`, true}, {`{"foo":"bar"}`, true}, {`{"foo":"bar","bar":{"baz":["qux"]}}`, true}, } func TestValid(t *testing.T) { for _, tt := range validTests { if ok := Valid([]byte(tt.data)); ok != tt.ok { t.Errorf("Valid(%#q) = %v, want %v", tt.data, ok, tt.ok) } } }
-
-
jsonld/tables.go (deleted)
-
@@ -1,218 +0,0 @@// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import "unicode/utf8" // safeSet holds the value true if the ASCII character with the given array // position can be represented inside a JSON string without any further // escaping. // // All values are true except for the ASCII control characters (0-31), the // double quote ("), and the backslash character ("\"). var safeSet = [utf8.RuneSelf]bool{ ' ': true, '!': true, '"': false, '#': true, '$': true, '%': true, '&': true, '\'': true, '(': true, ')': true, '*': true, '+': true, ',': true, '-': true, '.': true, '/': true, '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, ':': true, ';': true, '<': true, '=': true, '>': true, '?': true, '@': true, 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true, '[': true, '\\': false, ']': true, '^': true, '_': true, '`': true, 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true, 'y': true, 'z': true, '{': true, '|': true, '}': true, '~': true, '\u007f': true, } // htmlSafeSet holds the value true if the ASCII character with the given // array position can be safely represented inside a JSON string, embedded // inside of HTML <script> tags, without any additional escaping. // // All values are true except for the ASCII control characters (0-31), the // double quote ("), the backslash character ("\"), HTML opening and closing // tags ("<" and ">"), and the ampersand ("&"). var htmlSafeSet = [utf8.RuneSelf]bool{ ' ': true, '!': true, '"': false, '#': true, '$': true, '%': true, '&': false, '\'': true, '(': true, ')': true, '*': true, '+': true, ',': true, '-': true, '.': true, '/': true, '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true, '8': true, '9': true, ':': true, ';': true, '<': false, '=': true, '>': false, '?': true, '@': true, 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true, 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true, 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true, 'Y': true, 'Z': true, '[': true, '\\': false, ']': true, '^': true, '_': true, '`': true, 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true, 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true, 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true, 'y': true, 'z': true, '{': true, '|': true, '}': true, '~': true, '\u007f': true, }
-
-
jsonld/tags.go (deleted)
-
@@ -1,44 +0,0 @@// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import ( "strings" ) // tagOptions is the string following a comma in a struct field's "json" // tag, or the empty string. It does not include the leading comma. type tagOptions string // parseTag splits a struct field's json tag into its name and // comma-separated options. func parseTag(tag string) (string, tagOptions) { if idx := strings.Index(tag, ","); idx != -1 { return tag[:idx], tagOptions(tag[idx+1:]) } return tag, tagOptions("") } // Contains reports whether a comma-separated list of options // contains a particular substr flag. substr must be surrounded by a // string boundary or commas. func (o tagOptions) Contains(optionName string) bool { if len(o) == 0 { return false } s := string(o) for s != "" { var next string i := strings.Index(s, ",") if i >= 0 { s, next = s[:i], s[i+1:] } if s == optionName { return true } s = next } return false }
-
-
jsonld/tags_test.go (deleted)
-
@@ -1,28 +0,0 @@// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package jsonld import ( "testing" ) func TestTagParsing(t *testing.T) { name, opts := parseTag("field,foobar,foo") if name != "field" { t.Fatalf("name = %q, want field", name) } for _, tt := range []struct { opt string want bool }{ {"foobar", true}, {"foo", true}, {"bar", false}, } { if opts.Contains(tt.opt) != tt.want { t.Errorf("Contains(%q) = %v", tt.opt, !tt.want) } } }
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "time" )
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "reflect" "testing" "time"
-
-
-
@@ -1,6 +1,6 @@package activitypub import as "github.com/go-ap/activitypub.go/activitystreams" import as "github.com/go-ap/activitystreams" type ( // LikedCollection is a list of every object from all of the actor's Like activities,
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "reflect" "testing" )
-
-
-
@@ -1,6 +1,6 @@package activitypub import as "github.com/go-ap/activitypub.go/activitystreams" import as "github.com/go-ap/activitystreams" type ( // LikesCollection is a list of all Like activities with this object as the object property,
-
-
-
@@ -2,7 +2,7 @@ package activitypubimport ( "github.com/buger/jsonparser" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) // Source is intended to convey some sort of source from which the content markup was derived,
-
-
-
-
@@ -1,6 +1,6 @@package activitypub import as "github.com/go-ap/activitypub.go/activitystreams" import as "github.com/go-ap/activitystreams" type ( // OutboxStream contains activities the user has published,
-
-
-
@@ -4,7 +4,7 @@ import ("reflect" "testing" as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) func TestOutboxNew(t *testing.T) {
-
-
-
@@ -1,6 +1,6 @@package activitypub import as "github.com/go-ap/activitypub.go/activitystreams" import as "github.com/go-ap/activitystreams" type ( // SharesCollection is a list of all Announce activities with this object as the object property,
-
-
-
@@ -3,8 +3,8 @@ package testsimport ( "testing" a "github.com/go-ap/activitypub.go/activitystreams" j "github.com/go-ap/activitypub.go/jsonld" a "github.com/go-ap/activitystreams" j "github.com/go-ap/jsonld" "strings" )
-
-
-
@@ -4,7 +4,7 @@ package testsimport ( "fmt" a "github.com/go-ap/activitypub.go/activitystreams" a "github.com/go-ap/activitystreams" "testing" )
-
-
-
@@ -11,9 +11,9 @@ import ("time" "unsafe" ap "github.com/go-ap/activitypub.go/activitypub" a "github.com/go-ap/activitypub.go/activitystreams" j "github.com/go-ap/activitypub.go/jsonld" ap "github.com/go-ap/activitypub" a "github.com/go-ap/activitystreams" j "github.com/go-ap/jsonld" ) const dir = "./mocks"
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "time" )
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" "reflect" "testing" "time"
-
-
-
@@ -1,7 +1,7 @@package activitypub import ( as "github.com/go-ap/activitypub.go/activitystreams" as "github.com/go-ap/activitystreams" ) // ValidationErrors is an aggregated error interface that allows
-