Now let’s talk about R6 classes. They aren’t built into the base R distribution, but live in their own package, called R6.

The two major features of R6 that are super useful are:

  1. mutability, which means that you can modify an object in place, which is useful for maintaining state, and

  2. private versus public fields, which is especially useful if you want your object to act like an API.

library(here)
library(R6)
source(here("R/classes-R6.R"))

Making an new R6 object

We’re going to make a new object of class StatPackageResultR6 first. We do this by calling $new() on the StatsPackageResultR6 class:

stat_frame <- data.frame(group=c("setosa", "virginica", "versicolor"), pvalue=c(0.5, 0.2, 0.001))

my_stats_r6 <- StatPackageResultR6$new(data = iris, statistics = stat_frame)
class(my_stats_r6)
[1] "StatPackageResultR6" "R6"                 

What’s in the Object?

If we just use str() on our object, we’ll get information about the structure of the object. The first thing to note is that there are two main groupings: public and private.

str(my_stats_r6)
Classes 'StatPackageResultR6', 'R6' <StatPackageResultR6>
  Public:
    clone: function (deep = FALSE) 
    data: data.frame
    get_significant_results: function () 
    get_statistics: function () 
    get_threshold: function () 
    initialize: function (data, statistics) 
    print: function () 
    set_threshold: function (threshold) 
    statistics: data.frame
    validate: function () 
  Private:
    threshold: NULL 

Methods are attached to the object

If you look under public, you’ll notice that there’s a number of functions. These are the methods that are attached to the my_stats_r6 object. You access these methods using the $ operator.

my_stats_r6$get_statistics()

What about get_significant_results() method? Trying it, we get an error.

my_stats_r6$get_significant_results()
Error in my_stats_r6$get_significant_results() : Threshold is not set

Huh, we need to set a threshold. How do we do this?

Private versus Public

R6 has an additional feature that is very useful; private fields verus public fields. Private fields are provided as an argument to the private argument, which is a list.

Part of the reason for having private fields is that you don’t want the user to directly access these values. There is no way to get the threshold value without using an accessor method. If we try that:

my_stats_r6$get_threshold()
NULL

The threshold is not set for this object. We can set a value using set_threshold():

my_stats_r6$set_threshold(threshold = 0.02)

Whoa - there was no assignment operator! This is one of the features of R6 - they are processed in place.

my_stats_r6$get_threshold()
[1] 0.02

Now if we try get_significant_results it will work:

my_stats_r6$get_significant_results()

How do we define methods in R6?

Let’s take a look at the StatPackageResultR6 class. The first thing we notice is that there are two main arguments: public and private, which are both lists.

StatPackageResultR6 <- R6::R6Class(classname = "StatPackageResultR6",
            public = list(
              
              #functions and public fields go here
                  
              }),
            
            private=list(
              #private fields go here
            
              )
            )

We define public methods as functions that are arguments in the list in public:

StatPackageResultR6 <- R6::R6Class(classname = "StatPackageResultR6",
            public = list(
              #methods and fields defined here:
              
              get_significant_results = function(){
                
                  if(is.null(private$threshold)){
                    stop("Threshold is not set")
                  }
                
                  filtered_results <- self$statistics %>%
                    filter(pvalue < private$threshold)
                  
                  filtered_results
                  
              },
              
              # more methods defined below
                  
              }),
            
            private=list(
              #private fields go here
            
              )
            )

And our private field, threshold, is an argument to the private list:

StatPackageResultR6 <- R6::R6Class(classname = "StatPackageResultR6",
            public = list(
              
              #functions and public fields go here
                  
              }),
            
            private=list(
              threshold = NULL
            
              )
            )

Let’s take a look at the get_significant_results() method:

get_significant_results = function(){
                
                  if(is.null(private$threshold)){
                    stop("Threshold is not set")
                  }
                
                  filtered_results <- self$statistics %>%
                    filter(pvalue < private$threshold)
                  
                  filtered_results
                  
              }

The first thing to note is the line:

if(is.null(private$threshold)){

We’re accessing the threshold value using private, because it’s a private field.

The next thing to note is the line:

filtered_results <- self$statistics %>%

We access the statistics field using self. Why is it self and not public? This naming convention comes from other object programming languages.

Setting values: invisible(self)

When you set values, you have to end the method with invisible(self). We’re basically returning our modified object after we’ve set it.

set_threshold = function(threshold){
                private$threshold <- threshold
                invisible(self)
              }

Important method: $initialize()

One method you should always specify is $initialize, which defines the constructor for the method. This is the method that is used whenever we create a new object with $new():

              #this is what we use to initialize our object
              initialize = function(data, statistics){
                self$data <- data
                self$statistics <- statistics
                invisible(self)
              },

Rather annoying: specifiying methods outside of the class

The other thing to note is that you have to specify these functions as list arguments to the public list. Because they use self and private in the function, they can’t be defined as separate functions outside of the list.

For tidy-ness, and overall code legibility, you can use the $set() method to add individual methods to the class. For example, this is how we’ll add a $print() method to our class:

StatPackageResultR6$set(which = "public", name = "print", 
                        value = function() {
                          
                          print(head(self$data))
                          print(head(self$statistics))
                        }
                      )

Important Method: $validate()

The $validate() method lets you define a method to validate the contents of your R6 object, much like setValidity() let you do this for S4 objects.

StatPackageResultR6$set(which = "public", name = "validate", 
                        value = function() {
                          
      if(!is.data.frame(self$statistics)){
            warning("statistics field is not a data.frame")
            return(FALSE)
            }
                          
       if(!"pvalue" %in% colnames(self$statistics)){
            warning("statistics field doesn't contain 
                a pvalue column")
                            return(FALSE)
                          }
                          #return TRUE otherwise
                          return(TRUE)
                        }
)

Having a $validate() method is especially useful when getting and setting complex data types in fields.

my_stats_r6$validate()
[1] TRUE

Chaining Methods

What do you think the following does?

my_stats_r6$set_threshold(0.21)$get_significant_results()

Chaining multiple methods together is a style that is common in JavaScript and Python and can be done by chaining $methods

Maintaining State is Important: R6/Shiny

The main use case I’ve found for R6 in my work is for building data objects in Shiny. The data is encapsulated in an R6 object which can provide different formats of the data given a Shiny visualization.

I use R6 in my Shiny apps, for modularity reasons. The same data object is used for different visualizations, so I can design the visualizations to expect a certain format (long or wide). This gives me the flexibility of changing the internal format of the data fields in the object if necessary.

Here are my R6 Classes: https://github.com/laderast/flowDashboard/blob/master/R/classes.R

I don’t necessarily think this is the best implementation, but you can see what I did.

Inheritance

R6 objects can inherit from each other. Here we’re making a new class called AnovaResultR6, using the inherit= argument. Our AnovaResultR6 class has an additional field we’re calling groups.

We’re overriding our $initialize method for the StatPackageResultR6. It sets the groups field, and then uses super$initialize() to set the other fields in the object. super is the equivalent of NextMethod() in S3.

AnovaResultR6 <- R6::R6Class(classname = "AnovaResultR6",
                             inherit="StatPackageResultR6",
                             public = 
                               list(groups = NULL,
                                    
                                    initialize=function(data, statistics, groups){
                                      self$groups <- groups
                                      super$initialize(data, statistics)
                                      invisible(self)
                                    },
                                    
                                    print = function(){
                                   print(self$groups)
                                   super$print()
                                 })
                             )

Let’s make an AnovaResultR6 object:

stat_frame <- data.frame(group=c("setosa", "virginica", "versicolor"), pvalue=c(0.5, 0.2, 0.001))

anova_object <- AnovaResultR6$new(data=iris, 
                                  statistics=stat_frame, groups=c("setosa", 
                                                                  "virginica", 
                                                                  "versicolor"))

We can see that our AnovaResultR6 object inherits from StatPackageResultR6 and that it has an additional groups field in public.

str(anova_object)

And it can use the $get_statistics() method it inherited:

anova_object$get_statistics()

R6 Quirks: Copy By Reference

R6 objects are built on environments. This means that if you assign my_stats_r6 to a new object new_my_stats_r6, it’s just a pointer to the original object.

new_my_stats_r6 <- my_stats_r6

new_my_stats_r6$set_threshold(0.1)

my_stats_r6$get_threshold()

If you need to make a brand new object that is a separate copy of that object, you need to use the $clone() method:

new_my_stats_r6 <- my_stats_r6$clone()

new_my_stats_r6$set_threshold(0.4)

new_my_stats_r6$get_threshold()

my_stats_r6$get_threshold()

If your R6 object contains other R6 objects as fields and you want to clone these as well, you’ll have to additionally apply the deep=TRUE argument.

Note: R6 is Weird to most R users

You probably don’t want have your final results object as an R6 class. Mostly because most users aren’t familiar with R6 and using methods attached to an object. I learned this the hard way.

The one exception is when your package is going to be used by developers - they will probably be more familiar with the R6 object structure and getting things out of it.

Things we didn’t cover

  • R6 Classes also have an active slot, which has its uses.
  • Multiple inheritance
LS0tDQp0aXRsZTogIlI2IENsYXNzZXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpOb3cgbGV0J3MgdGFsayBhYm91dCBSNiBjbGFzc2VzLiBUaGV5IGFyZW4ndCBidWlsdCBpbnRvIHRoZSBiYXNlIFIgZGlzdHJpYnV0aW9uLCBidXQgbGl2ZSBpbiB0aGVpciBvd24gcGFja2FnZSwgY2FsbGVkIGBSNmAuDQoNClRoZSB0d28gbWFqb3IgZmVhdHVyZXMgb2YgUjYgdGhhdCBhcmUgc3VwZXIgdXNlZnVsIGFyZToNCg0KMS4gKm11dGFiaWxpdHkqLCB3aGljaCBtZWFucyB0aGF0IHlvdSBjYW4gbW9kaWZ5IGFuIG9iamVjdCBpbiBwbGFjZSwgd2hpY2ggaXMgdXNlZnVsIGZvciBtYWludGFpbmluZyBzdGF0ZSwgYW5kDQoNCjIuICpwcml2YXRlKiB2ZXJzdXMgKnB1YmxpYyogZmllbGRzLCB3aGljaCBpcyBlc3BlY2lhbGx5IHVzZWZ1bCBpZiB5b3Ugd2FudCB5b3VyIG9iamVjdCB0byBhY3QgbGlrZSBhbiBBUEkuIA0KDQpgYGB7cn0NCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoUjYpDQpzb3VyY2UoaGVyZSgiUi9jbGFzc2VzLVI2LlIiKSkNCmBgYA0KDQojIyBNYWtpbmcgYW4gbmV3IFI2IG9iamVjdA0KDQpXZSdyZSBnb2luZyB0byBtYWtlIGEgbmV3IG9iamVjdCBvZiBjbGFzcyBgU3RhdFBhY2thZ2VSZXN1bHRSNmAgZmlyc3QuIFdlIGRvIHRoaXMgYnkgY2FsbGluZyBgJG5ldygpYCBvbiB0aGUgYFN0YXRzUGFja2FnZVJlc3VsdFI2YCBjbGFzczoNCg0KYGBge3J9DQpzdGF0X2ZyYW1lIDwtIGRhdGEuZnJhbWUoZ3JvdXA9Yygic2V0b3NhIiwgInZpcmdpbmljYSIsICJ2ZXJzaWNvbG9yIiksIHB2YWx1ZT1jKDAuNSwgMC4yLCAwLjAwMSkpDQoNCm15X3N0YXRzX3I2IDwtIFN0YXRQYWNrYWdlUmVzdWx0UjYkbmV3KGRhdGEgPSBpcmlzLCBzdGF0aXN0aWNzID0gc3RhdF9mcmFtZSkNCmNsYXNzKG15X3N0YXRzX3I2KQ0KYGBgDQoNCiMjIFdoYXQncyBpbiB0aGUgT2JqZWN0Pw0KDQpJZiB3ZSBqdXN0IHVzZSBgc3RyKClgIG9uIG91ciBvYmplY3QsIHdlJ2xsIGdldCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgc3RydWN0dXJlIG9mIHRoZSBvYmplY3QuIFRoZSBmaXJzdCB0aGluZyB0byBub3RlIGlzIHRoYXQgdGhlcmUgYXJlIHR3byBtYWluIGdyb3VwaW5nczogYHB1YmxpY2AgYW5kIGBwcml2YXRlYC4gDQoNCmBgYHtyfQ0Kc3RyKG15X3N0YXRzX3I2KQ0KYGBgDQoNCiMjIE1ldGhvZHMgYXJlIGF0dGFjaGVkIHRvIHRoZSBvYmplY3QNCg0KSWYgeW91IGxvb2sgdW5kZXIgYHB1YmxpY2AsIHlvdSdsbCBub3RpY2UgdGhhdCB0aGVyZSdzIGEgbnVtYmVyIG9mIGZ1bmN0aW9ucy4gVGhlc2UgYXJlIHRoZSAqbWV0aG9kcyogdGhhdCBhcmUgYXR0YWNoZWQgdG8gdGhlIGBteV9zdGF0c19yNmAgb2JqZWN0LiBZb3UgYWNjZXNzIHRoZXNlIG1ldGhvZHMgdXNpbmcgdGhlIGAkYCBvcGVyYXRvci4gDQoNCmBgYHtyfQ0KbXlfc3RhdHNfcjYkZ2V0X3N0YXRpc3RpY3MoKQ0KYGBgDQoNCldoYXQgYWJvdXQgYGdldF9zaWduaWZpY2FudF9yZXN1bHRzKClgIG1ldGhvZD8gVHJ5aW5nIGl0LCB3ZSBnZXQgYW4gZXJyb3IuDQoNCmBgYHtyfQ0KbXlfc3RhdHNfcjYkZ2V0X3NpZ25pZmljYW50X3Jlc3VsdHMoKQ0KYGBgDQoNCkh1aCwgd2UgbmVlZCB0byBzZXQgYSB0aHJlc2hvbGQuIEhvdyBkbyB3ZSBkbyB0aGlzPw0KDQojIyBQcml2YXRlIHZlcnN1cyBQdWJsaWMNCg0KUjYgaGFzIGFuIGFkZGl0aW9uYWwgZmVhdHVyZSB0aGF0IGlzIHZlcnkgdXNlZnVsOyAqcHJpdmF0ZSogZmllbGRzIHZlcnVzICpwdWJsaWMqIGZpZWxkcy4gUHJpdmF0ZSBmaWVsZHMgYXJlIHByb3ZpZGVkIGFzIGFuIGFyZ3VtZW50IHRvIHRoZSBgcHJpdmF0ZWAgYXJndW1lbnQsIHdoaWNoIGlzIGEgbGlzdC4NCg0KUGFydCBvZiB0aGUgcmVhc29uIGZvciBoYXZpbmcgKnByaXZhdGUqIGZpZWxkcyBpcyB0aGF0IHlvdSBkb24ndCB3YW50IHRoZSB1c2VyIHRvIGRpcmVjdGx5IGFjY2VzcyB0aGVzZSB2YWx1ZXMuIFRoZXJlIGlzIG5vIHdheSB0byBnZXQgdGhlIGB0aHJlc2hvbGRgIHZhbHVlIHdpdGhvdXQgdXNpbmcgYW4gYGFjY2Vzc29yYCBtZXRob2QuIElmIHdlIHRyeSB0aGF0Og0KDQpgYGB7cn0NCm15X3N0YXRzX3I2JGdldF90aHJlc2hvbGQoKQ0KDQpgYGANCg0KVGhlIHRocmVzaG9sZCBpcyBub3Qgc2V0IGZvciB0aGlzIG9iamVjdC4gV2UgY2FuIHNldCBhIHZhbHVlIHVzaW5nIGBzZXRfdGhyZXNob2xkKClgOg0KDQpgYGB7cn0NCm15X3N0YXRzX3I2JHNldF90aHJlc2hvbGQodGhyZXNob2xkID0gMC4wMikNCmBgYA0KDQpXaG9hIC0gdGhlcmUgd2FzIG5vIGFzc2lnbm1lbnQgb3BlcmF0b3IhIFRoaXMgaXMgb25lIG9mIHRoZSBmZWF0dXJlcyBvZiBSNiAtIHRoZXkgYXJlIHByb2Nlc3NlZCBpbiBwbGFjZS4NCg0KYGBge3J9DQpteV9zdGF0c19yNiRnZXRfdGhyZXNob2xkKCkNCmBgYA0KDQpOb3cgaWYgd2UgdHJ5IGBnZXRfc2lnbmlmaWNhbnRfcmVzdWx0c2AgaXQgd2lsbCB3b3JrOg0KDQpgYGB7cn0NCm15X3N0YXRzX3I2JGdldF9zaWduaWZpY2FudF9yZXN1bHRzKCkNCmBgYA0KDQojIEhvdyBkbyB3ZSBkZWZpbmUgbWV0aG9kcyBpbiBSNj8NCg0KTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGBTdGF0UGFja2FnZVJlc3VsdFI2YCBjbGFzcy4gVGhlIGZpcnN0IHRoaW5nIHdlIG5vdGljZSBpcyB0aGF0IHRoZXJlIGFyZSB0d28gbWFpbiBhcmd1bWVudHM6IGBwdWJsaWNgIGFuZCBgcHJpdmF0ZWAsIHdoaWNoIGFyZSBib3RoIGxpc3RzLg0KDQpgYGANClN0YXRQYWNrYWdlUmVzdWx0UjYgPC0gUjY6OlI2Q2xhc3MoY2xhc3NuYW1lID0gIlN0YXRQYWNrYWdlUmVzdWx0UjYiLA0KICAgICAgICAgICAgcHVibGljID0gbGlzdCgNCiAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICNmdW5jdGlvbnMgYW5kIHB1YmxpYyBmaWVsZHMgZ28gaGVyZQ0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgIH0pLA0KICAgICAgICAgICAgDQogICAgICAgICAgICBwcml2YXRlPWxpc3QoDQogICAgICAgICAgICAgICNwcml2YXRlIGZpZWxkcyBnbyBoZXJlDQogICAgICAgICAgICANCiAgICAgICAgICAgICAgKQ0KICAgICAgICAgICAgKQ0KDQpgYGANCg0KV2UgZGVmaW5lIHB1YmxpYyBtZXRob2RzIGFzIGZ1bmN0aW9ucyB0aGF0IGFyZSBhcmd1bWVudHMgaW4gdGhlIGxpc3QgaW4gYHB1YmxpY2A6DQoNCg0KYGBgDQpTdGF0UGFja2FnZVJlc3VsdFI2IDwtIFI2OjpSNkNsYXNzKGNsYXNzbmFtZSA9ICJTdGF0UGFja2FnZVJlc3VsdFI2IiwNCiAgICAgICAgICAgIHB1YmxpYyA9IGxpc3QoDQogICAgICAgICAgICAgICNtZXRob2RzIGFuZCBmaWVsZHMgZGVmaW5lZCBoZXJlOg0KICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgZ2V0X3NpZ25pZmljYW50X3Jlc3VsdHMgPSBmdW5jdGlvbigpew0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgaWYoaXMubnVsbChwcml2YXRlJHRocmVzaG9sZCkpew0KICAgICAgICAgICAgICAgICAgICBzdG9wKCJUaHJlc2hvbGQgaXMgbm90IHNldCIpDQogICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICBmaWx0ZXJlZF9yZXN1bHRzIDwtIHNlbGYkc3RhdGlzdGljcyAlPiUNCiAgICAgICAgICAgICAgICAgICAgZmlsdGVyKHB2YWx1ZSA8IHByaXZhdGUkdGhyZXNob2xkKQ0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICBmaWx0ZXJlZF9yZXN1bHRzDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgfSwNCiAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICMgbW9yZSBtZXRob2RzIGRlZmluZWQgYmVsb3cNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICB9KSwNCiAgICAgICAgICAgIA0KICAgICAgICAgICAgcHJpdmF0ZT1saXN0KA0KICAgICAgICAgICAgICAjcHJpdmF0ZSBmaWVsZHMgZ28gaGVyZQ0KICAgICAgICAgICAgDQogICAgICAgICAgICAgICkNCiAgICAgICAgICAgICkNCmBgYA0KDQpBbmQgb3VyIHByaXZhdGUgZmllbGQsIGB0aHJlc2hvbGRgLCBpcyBhbiBhcmd1bWVudCB0byB0aGUgYHByaXZhdGVgIGxpc3Q6DQoNCmBgYA0KU3RhdFBhY2thZ2VSZXN1bHRSNiA8LSBSNjo6UjZDbGFzcyhjbGFzc25hbWUgPSAiU3RhdFBhY2thZ2VSZXN1bHRSNiIsDQogICAgICAgICAgICBwdWJsaWMgPSBsaXN0KA0KICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgI2Z1bmN0aW9ucyBhbmQgcHVibGljIGZpZWxkcyBnbyBoZXJlDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgfSksDQogICAgICAgICAgICANCiAgICAgICAgICAgIHByaXZhdGU9bGlzdCgNCiAgICAgICAgICAgICAgdGhyZXNob2xkID0gTlVMTA0KICAgICAgICAgICAgDQogICAgICAgICAgICAgICkNCiAgICAgICAgICAgICkNCg0KYGBgDQoNCkxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBgZ2V0X3NpZ25pZmljYW50X3Jlc3VsdHMoKWAgbWV0aG9kOg0KDQpgYGANCmdldF9zaWduaWZpY2FudF9yZXN1bHRzID0gZnVuY3Rpb24oKXsNCiAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgIGlmKGlzLm51bGwocHJpdmF0ZSR0aHJlc2hvbGQpKXsNCiAgICAgICAgICAgICAgICAgICAgc3RvcCgiVGhyZXNob2xkIGlzIG5vdCBzZXQiKQ0KICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgZmlsdGVyZWRfcmVzdWx0cyA8LSBzZWxmJHN0YXRpc3RpY3MgJT4lDQogICAgICAgICAgICAgICAgICAgIGZpbHRlcihwdmFsdWUgPCBwcml2YXRlJHRocmVzaG9sZCkNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgZmlsdGVyZWRfcmVzdWx0cw0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgIH0NCmBgYA0KDQpUaGUgZmlyc3QgdGhpbmcgdG8gbm90ZSBpcyB0aGUgbGluZTogDQoNCmBpZihpcy5udWxsKHByaXZhdGUkdGhyZXNob2xkKSl7YA0KDQpXZSdyZSBhY2Nlc3NpbmcgdGhlIGB0aHJlc2hvbGRgIHZhbHVlIHVzaW5nIGBwcml2YXRlYCwgYmVjYXVzZSBpdCdzIGEgcHJpdmF0ZSBmaWVsZC4NCg0KVGhlIG5leHQgdGhpbmcgdG8gbm90ZSBpcyB0aGUgbGluZToNCg0KYGZpbHRlcmVkX3Jlc3VsdHMgPC0gc2VsZiRzdGF0aXN0aWNzICU+JWANCg0KV2UgYWNjZXNzIHRoZSBgc3RhdGlzdGljc2AgZmllbGQgdXNpbmcgYHNlbGZgLiBXaHkgaXMgaXQgYHNlbGZgIGFuZCBub3QgYHB1YmxpY2A/IFRoaXMgbmFtaW5nIGNvbnZlbnRpb24gY29tZXMgZnJvbSBvdGhlciBvYmplY3QgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLg0KDQojIFNldHRpbmcgdmFsdWVzOiBgaW52aXNpYmxlKHNlbGYpYA0KDQpXaGVuIHlvdSBzZXQgdmFsdWVzLCB5b3UgaGF2ZSB0byBlbmQgdGhlIG1ldGhvZCB3aXRoIGBpbnZpc2libGUoc2VsZilgLiBXZSdyZSBiYXNpY2FsbHkgcmV0dXJuaW5nIG91ciBtb2RpZmllZCBvYmplY3QgYWZ0ZXIgd2UndmUgc2V0IGl0LiANCg0KYGBgDQpzZXRfdGhyZXNob2xkID0gZnVuY3Rpb24odGhyZXNob2xkKXsNCiAgICAgICAgICAgICAgICBwcml2YXRlJHRocmVzaG9sZCA8LSB0aHJlc2hvbGQNCiAgICAgICAgICAgICAgICBpbnZpc2libGUoc2VsZikNCiAgICAgICAgICAgICAgfQ0KYGBgDQoNCiMgSW1wb3J0YW50IG1ldGhvZDogYCRpbml0aWFsaXplKClgDQoNCk9uZSBtZXRob2QgeW91IHNob3VsZCBhbHdheXMgc3BlY2lmeSBpcyBgJGluaXRpYWxpemVgLCB3aGljaCBkZWZpbmVzIHRoZSAqY29uc3RydWN0b3IqIGZvciB0aGUgbWV0aG9kLiBUaGlzIGlzIHRoZSBtZXRob2QgdGhhdCBpcyB1c2VkIHdoZW5ldmVyIHdlIGNyZWF0ZSBhIG5ldyBvYmplY3Qgd2l0aCBgJG5ldygpYDoNCg0KYGBgDQogICAgICAgICAgICAgICN0aGlzIGlzIHdoYXQgd2UgdXNlIHRvIGluaXRpYWxpemUgb3VyIG9iamVjdA0KICAgICAgICAgICAgICBpbml0aWFsaXplID0gZnVuY3Rpb24oZGF0YSwgc3RhdGlzdGljcyl7DQogICAgICAgICAgICAgICAgc2VsZiRkYXRhIDwtIGRhdGENCiAgICAgICAgICAgICAgICBzZWxmJHN0YXRpc3RpY3MgPC0gc3RhdGlzdGljcw0KICAgICAgICAgICAgICAgIGludmlzaWJsZShzZWxmKQ0KICAgICAgICAgICAgICB9LA0KYGBgDQoNCg0KIyBSYXRoZXIgYW5ub3lpbmc6IHNwZWNpZml5aW5nIG1ldGhvZHMgb3V0c2lkZSBvZiB0aGUgY2xhc3MNCg0KVGhlIG90aGVyIHRoaW5nIHRvIG5vdGUgaXMgdGhhdCB5b3UgaGF2ZSB0byBzcGVjaWZ5IHRoZXNlIGZ1bmN0aW9ucyBhcyBsaXN0IGFyZ3VtZW50cyB0byB0aGUgYHB1YmxpY2AgbGlzdC4gQmVjYXVzZSB0aGV5IHVzZSBgc2VsZmAgYW5kIGBwcml2YXRlYCBpbiB0aGUgZnVuY3Rpb24sIHRoZXkgY2FuJ3QgYmUgZGVmaW5lZCBhcyBzZXBhcmF0ZSBmdW5jdGlvbnMgb3V0c2lkZSBvZiB0aGUgbGlzdC4NCg0KRm9yIHRpZHktbmVzcywgYW5kIG92ZXJhbGwgY29kZSBsZWdpYmlsaXR5LCB5b3UgY2FuIHVzZSB0aGUgYCRzZXQoKWAgbWV0aG9kIHRvIGFkZCBpbmRpdmlkdWFsIG1ldGhvZHMgdG8gdGhlIGNsYXNzLiBGb3IgZXhhbXBsZSwgdGhpcyBpcyBob3cgd2UnbGwgYWRkIGEgYCRwcmludCgpYCBtZXRob2QgdG8gb3VyIGNsYXNzOg0KDQpgYGANClN0YXRQYWNrYWdlUmVzdWx0UjYkc2V0KHdoaWNoID0gInB1YmxpYyIsIG5hbWUgPSAicHJpbnQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZnVuY3Rpb24oKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludChoZWFkKHNlbGYkZGF0YSkpDQogICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50KGhlYWQoc2VsZiRzdGF0aXN0aWNzKSkNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICApDQpgYGANCg0KIyBJbXBvcnRhbnQgTWV0aG9kOiBgJHZhbGlkYXRlKClgDQoNClRoZSBgJHZhbGlkYXRlKClgIG1ldGhvZCBsZXRzIHlvdSBkZWZpbmUgYSBtZXRob2QgdG8gdmFsaWRhdGUgdGhlIGNvbnRlbnRzIG9mIHlvdXIgUjYgb2JqZWN0LCBtdWNoIGxpa2UgYHNldFZhbGlkaXR5KClgIGxldCB5b3UgZG8gdGhpcyBmb3IgUzQgb2JqZWN0cy4NCg0KYGBgDQpTdGF0UGFja2FnZVJlc3VsdFI2JHNldCh3aGljaCA9ICJwdWJsaWMiLCBuYW1lID0gInZhbGlkYXRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGZ1bmN0aW9uKCkgew0KICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgIGlmKCFpcy5kYXRhLmZyYW1lKHNlbGYkc3RhdGlzdGljcykpew0KICAgICAgICAgICAgd2FybmluZygic3RhdGlzdGljcyBmaWVsZCBpcyBub3QgYSBkYXRhLmZyYW1lIikNCiAgICAgICAgICAgIHJldHVybihGQUxTRSkNCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgaWYoISJwdmFsdWUiICVpbiUgY29sbmFtZXMoc2VsZiRzdGF0aXN0aWNzKSl7DQogICAgICAgICAgICB3YXJuaW5nKCJzdGF0aXN0aWNzIGZpZWxkIGRvZXNuJ3QgY29udGFpbiANCiAgICAgICAgICAgICAgICBhIHB2YWx1ZSBjb2x1bW4iKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybihGQUxTRSkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAjcmV0dXJuIFRSVUUgb3RoZXJ3aXNlDQogICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybihUUlVFKQ0KICAgICAgICAgICAgICAgICAgICAgICAgfQ0KKQ0KYGBgDQoNCkhhdmluZyBhIGAkdmFsaWRhdGUoKWAgbWV0aG9kIGlzIGVzcGVjaWFsbHkgdXNlZnVsIHdoZW4gZ2V0dGluZyBhbmQgc2V0dGluZyBjb21wbGV4IGRhdGEgdHlwZXMgaW4gZmllbGRzLg0KDQpgYGB7cn0NCm15X3N0YXRzX3I2JHZhbGlkYXRlKCkNCmBgYA0KDQojIyBDaGFpbmluZyBNZXRob2RzDQoNCldoYXQgZG8geW91IHRoaW5rIHRoZSBmb2xsb3dpbmcgZG9lcz8NCg0KYGBge3J9DQpteV9zdGF0c19yNiRzZXRfdGhyZXNob2xkKDAuMjEpJGdldF9zaWduaWZpY2FudF9yZXN1bHRzKCkNCmBgYA0KDQpDaGFpbmluZyBtdWx0aXBsZSBtZXRob2RzIHRvZ2V0aGVyIGlzIGEgc3R5bGUgdGhhdCBpcyBjb21tb24gaW4gSmF2YVNjcmlwdCBhbmQgUHl0aG9uIGFuZCBjYW4gYmUgZG9uZSBieSBjaGFpbmluZyBgJG1ldGhvZHNgDQoNCiMjIE1haW50YWluaW5nIFN0YXRlIGlzIEltcG9ydGFudDogUjYvU2hpbnkNCg0KVGhlIG1haW4gdXNlIGNhc2UgSSd2ZSBmb3VuZCBmb3IgUjYgaW4gbXkgd29yayBpcyBmb3IgYnVpbGRpbmcgZGF0YSBvYmplY3RzIGluIFNoaW55LiBUaGUgZGF0YSBpcyBlbmNhcHN1bGF0ZWQgaW4gYW4gUjYgb2JqZWN0IHdoaWNoIGNhbiBwcm92aWRlIGRpZmZlcmVudCBmb3JtYXRzIG9mIHRoZSBkYXRhIGdpdmVuIGEgU2hpbnkgdmlzdWFsaXphdGlvbi4NCg0KSSB1c2UgUjYgaW4gbXkgU2hpbnkgYXBwcywgZm9yIG1vZHVsYXJpdHkgcmVhc29ucy4gVGhlIHNhbWUgZGF0YSBvYmplY3QgaXMgdXNlZCBmb3IgZGlmZmVyZW50IHZpc3VhbGl6YXRpb25zLCBzbyBJIGNhbiBkZXNpZ24gdGhlIHZpc3VhbGl6YXRpb25zIHRvIGV4cGVjdCBhIGNlcnRhaW4gZm9ybWF0IChsb25nIG9yIHdpZGUpLiBUaGlzIGdpdmVzIG1lIHRoZSBmbGV4aWJpbGl0eSBvZiBjaGFuZ2luZyB0aGUgaW50ZXJuYWwgZm9ybWF0IG9mIHRoZSBkYXRhIGZpZWxkcyBpbiB0aGUgb2JqZWN0IGlmIG5lY2Vzc2FyeS4gIA0KDQpIZXJlIGFyZSBteSBSNiBDbGFzc2VzOiBodHRwczovL2dpdGh1Yi5jb20vbGFkZXJhc3QvZmxvd0Rhc2hib2FyZC9ibG9iL21hc3Rlci9SL2NsYXNzZXMuUg0KDQpJIGRvbid0IG5lY2Vzc2FyaWx5IHRoaW5rIHRoaXMgaXMgdGhlIGJlc3QgaW1wbGVtZW50YXRpb24sIGJ1dCB5b3UgY2FuIHNlZSB3aGF0IEkgZGlkLg0KDQojIyBJbmhlcml0YW5jZQ0KDQpSNiBvYmplY3RzIGNhbiBpbmhlcml0IGZyb20gZWFjaCBvdGhlci4gSGVyZSB3ZSdyZSBtYWtpbmcgYSBuZXcgY2xhc3MgY2FsbGVkIGBBbm92YVJlc3VsdFI2YCwgdXNpbmcgdGhlIGBpbmhlcml0PWAgYXJndW1lbnQuIE91ciBgQW5vdmFSZXN1bHRSNmAgY2xhc3MgaGFzIGFuIGFkZGl0aW9uYWwgZmllbGQgd2UncmUgY2FsbGluZyBgZ3JvdXBzYC4gIA0KDQpXZSdyZSBvdmVycmlkaW5nIG91ciBgJGluaXRpYWxpemVgIG1ldGhvZCBmb3IgdGhlIGBTdGF0UGFja2FnZVJlc3VsdFI2YC4gSXQgc2V0cyB0aGUgYGdyb3Vwc2AgZmllbGQsIGFuZCB0aGVuIHVzZXMgYHN1cGVyJGluaXRpYWxpemUoKWAgdG8gc2V0IHRoZSBvdGhlciBmaWVsZHMgaW4gdGhlIG9iamVjdC4gYHN1cGVyYCBpcyB0aGUgZXF1aXZhbGVudCBvZiBgTmV4dE1ldGhvZCgpYCBpbiBTMy4NCg0KYGBgDQpBbm92YVJlc3VsdFI2IDwtIFI2OjpSNkNsYXNzKGNsYXNzbmFtZSA9ICJBbm92YVJlc3VsdFI2IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5oZXJpdD0iU3RhdFBhY2thZ2VSZXN1bHRSNiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1YmxpYyA9IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QoZ3JvdXBzID0gTlVMTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbGl6ZT1mdW5jdGlvbihkYXRhLCBzdGF0aXN0aWNzLCBncm91cHMpew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmJGdyb3VwcyA8LSBncm91cHMNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIkaW5pdGlhbGl6ZShkYXRhLCBzdGF0aXN0aWNzKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnZpc2libGUoc2VsZikNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50ID0gZnVuY3Rpb24oKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnQoc2VsZiRncm91cHMpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyJHByaW50KCkNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkNCmBgYA0KDQoNCkxldCdzIG1ha2UgYW4gYEFub3ZhUmVzdWx0UjZgIG9iamVjdDoNCg0KYGBge3J9DQpzdGF0X2ZyYW1lIDwtIGRhdGEuZnJhbWUoZ3JvdXA9Yygic2V0b3NhIiwgInZpcmdpbmljYSIsICJ2ZXJzaWNvbG9yIiksIHB2YWx1ZT1jKDAuNSwgMC4yLCAwLjAwMSkpDQoNCmFub3ZhX29iamVjdCA8LSBBbm92YVJlc3VsdFI2JG5ldyhkYXRhPWlyaXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRpc3RpY3M9c3RhdF9mcmFtZSwgZ3JvdXBzPWMoInNldG9zYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInZpcmdpbmljYSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInZlcnNpY29sb3IiKSkNCmBgYA0KDQpXZSBjYW4gc2VlIHRoYXQgb3VyIGBBbm92YVJlc3VsdFI2YCBvYmplY3QgaW5oZXJpdHMgZnJvbSBgU3RhdFBhY2thZ2VSZXN1bHRSNmAgYW5kIHRoYXQgaXQgaGFzIGFuIGFkZGl0aW9uYWwgYGdyb3Vwc2AgZmllbGQgaW4gcHVibGljLg0KDQpgYGB7cn0NCnN0cihhbm92YV9vYmplY3QpDQpgYGANCg0KQW5kIGl0IGNhbiB1c2UgdGhlIGAkZ2V0X3N0YXRpc3RpY3MoKWAgbWV0aG9kIGl0IGluaGVyaXRlZDoNCg0KYGBge3J9DQphbm92YV9vYmplY3QkZ2V0X3N0YXRpc3RpY3MoKQ0KYGBgDQoNCiMjIFI2IFF1aXJrczogQ29weSBCeSBSZWZlcmVuY2UNCg0KUjYgb2JqZWN0cyBhcmUgYnVpbHQgb24gZW52aXJvbm1lbnRzLiBUaGlzIG1lYW5zIHRoYXQgaWYgeW91IGFzc2lnbiBgbXlfc3RhdHNfcjZgIHRvIGEgbmV3IG9iamVjdCBgbmV3X215X3N0YXRzX3I2YCwgaXQncyBqdXN0IGEgcG9pbnRlciB0byB0aGUgb3JpZ2luYWwgb2JqZWN0Lg0KDQpgYGB7cn0NCm5ld19teV9zdGF0c19yNiA8LSBteV9zdGF0c19yNg0KDQpuZXdfbXlfc3RhdHNfcjYkc2V0X3RocmVzaG9sZCgwLjEpDQoNCm15X3N0YXRzX3I2JGdldF90aHJlc2hvbGQoKQ0KYGBgDQoNCklmIHlvdSBuZWVkIHRvIG1ha2UgYSBicmFuZCBuZXcgb2JqZWN0IHRoYXQgaXMgYSBzZXBhcmF0ZSBjb3B5IG9mIHRoYXQgb2JqZWN0LCB5b3UgbmVlZCB0byB1c2UgdGhlIGAkY2xvbmUoKWAgbWV0aG9kOg0KDQpgYGB7cn0NCm5ld19teV9zdGF0c19yNiA8LSBteV9zdGF0c19yNiRjbG9uZSgpDQoNCm5ld19teV9zdGF0c19yNiRzZXRfdGhyZXNob2xkKDAuNCkNCg0KbmV3X215X3N0YXRzX3I2JGdldF90aHJlc2hvbGQoKQ0KDQpteV9zdGF0c19yNiRnZXRfdGhyZXNob2xkKCkNCg0KYGBgDQoNCklmIHlvdXIgUjYgb2JqZWN0IGNvbnRhaW5zIG90aGVyIFI2IG9iamVjdHMgYXMgZmllbGRzIGFuZCB5b3Ugd2FudCB0byBjbG9uZSB0aGVzZSBhcyB3ZWxsLCB5b3UnbGwgaGF2ZSB0byBhZGRpdGlvbmFsbHkgYXBwbHkgdGhlIGBkZWVwPVRSVUVgIGFyZ3VtZW50Lg0KDQojIyBOb3RlOiBSNiBpcyBXZWlyZCB0byBtb3N0IFIgdXNlcnMNCg0KWW91IHByb2JhYmx5IGRvbid0IHdhbnQgaGF2ZSB5b3VyIGZpbmFsIHJlc3VsdHMgb2JqZWN0IGFzIGFuIFI2IGNsYXNzLiBNb3N0bHkgYmVjYXVzZSBtb3N0IHVzZXJzIGFyZW4ndCBmYW1pbGlhciB3aXRoIFI2IGFuZCB1c2luZyBtZXRob2RzIGF0dGFjaGVkIHRvIGFuIG9iamVjdC4gSSBsZWFybmVkIHRoaXMgdGhlIGhhcmQgd2F5Lg0KDQpUaGUgb25lIGV4Y2VwdGlvbiBpcyB3aGVuIHlvdXIgcGFja2FnZSBpcyBnb2luZyB0byBiZSB1c2VkIGJ5IGRldmVsb3BlcnMgLSB0aGV5IHdpbGwgcHJvYmFibHkgYmUgbW9yZSBmYW1pbGlhciB3aXRoIHRoZSBSNiBvYmplY3Qgc3RydWN0dXJlIGFuZCBnZXR0aW5nIHRoaW5ncyBvdXQgb2YgaXQuDQoNCiMjIFRoaW5ncyB3ZSBkaWRuJ3QgY292ZXINCg0KLSBSNiBDbGFzc2VzIGFsc28gaGF2ZSBhbiBgYWN0aXZlYCBzbG90LCB3aGljaCBoYXMgaXRzIHVzZXMuIA0KLSBNdWx0aXBsZSBpbmhlcml0YW5jZQ0KDQojIyBSZXNvdXJjZXMNCg0KaHR0cHM6Ly9hZHYtci5oYWRsZXkubnovcjYuaHRtbA0KDQo=